0

我替换了以下代码

(*dataset_p)[*term_count_p - 9] = ERL_DRV_ATOM;
(*dataset_p)[*term_count_p - 8] = drv->atom_error;
(*dataset_p)[*term_count_p - 7] = ERL_DRV_INT;
(*dataset_p)[*term_count_p - 6] = error_code;
(*dataset_p)[*term_count_p - 5] = ERL_DRV_STRING;
(*dataset_p)[*term_count_p - 4] = (ErlDrvTermData) error;
(*dataset_p)[*term_count_p - 3] = strlen(error);
(*dataset_p)[*term_count_p - 2] = ERL_DRV_TUPLE;
(*dataset_p)[*term_count_p - 1] = 3;

(其中dataset_p有类型ErlDrvTermData**并且term_count_pint*

append_to_dataset(9, *dataset_p, *term_count_p,
  ERL_DRV_ATOM, drv->atom_error,
  ERL_DRV_INT, error_code,
  ERL_DRV_STRING, (ErlDrvTermData) error, strlen(error),
  ERL_DRV_TUPLE, 3);

其中append_to_dataset定义为

void append_to_dataset(int n, ErlDrvTermData* dataset, int term_count, ...) {
  int i;
  va_list new_terms;
  va_start(new_terms, term_count);

  for (i = -n; i < 0; i++) {
    dataset[term_count + i] = va_arg(new_terms, ErlDrvTermData);
  }
  va_end(new_terms);
}

(差异看出这是全部差异)。在我看来,行为应该完全相同,但是当测试通过原始代码时,新版本失败并显示错误消息:

HUGE size (47278999994405)
make: *** [test] Aborted

我怎么了?

4

1 回答 1

1

根据第一个代码片段中赋值右侧的表达式类型,这两个代码片段可能不等价。

变量参数经过默认参数提升,但没有其他转换(与调用原型函数相反,如果参数与赋值兼容,则在必要时转换参数)。要使第二个代码正常工作,它们必须是类型ErlDrvTermData,而该类型又必须与其默认提升的类型相同,才能通过 正确获取相应的参数va_arg

特别是,除了前两个(不是变量参数)之外的每个参数都需要一个显式转换才能正确转换:

append_to_dataset(9, *dataset_p, *term_count_p,
  (ErlDrvTermData)ERL_DRV_ATOM, (ErlDrvTermData)drv->atom_error,
  (ErlDrvTermData)ERL_DRV_INT, (ErlDrvTermData)error_code,
  (ErlDrvTermData)ERL_DRV_STRING,
  (ErlDrvTermData) error, (ErlDrvTermData)strlen(error),
  (ErlDrvTermData)ERL_DRV_TUPLE, 3);

假设转换是保值的。ErlDrvTermData例如,如果typedefed 为 a short,则必须将其作为 an 获取int

dataset[term_count + i] = va_arg(new_terms, int);
于 2014-10-10T20:54:47.147 回答