我替换了以下代码
(*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_p
是 int*
(
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
我做错了什么?
根据第一个代码段中赋值右侧的表达式类型,这两个代码段可能不等效。
变量参数会进行默认的参数提升,但没有其他转换(与调用原型函数相反,如果参数与赋值兼容,则在必要时转换参数(。要使第二个代码正常工作,它们必须是 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
被typedef
到一个short
,则必须将其作为int
获取:
dataset[term_count + i] = va_arg(new_terms, int);