Apple Silicon(arm64)平台Clang编译的C函数使用stdarg出现异常的问题咨询
Apple Silicon(arm64)平台Clang编译的C函数使用stdarg出现异常的问题咨询
以下函数MsCommand_push在使用Apple clang version 15.0.0 (clang-1500.3.9.4)编译时无法正常工作。它的设计目的是接收可变数量的指向空终止字符串的char指针作为输入,并将这些字符串追加到一个缓冲区中——作为命令行解释器的一部分,用来填充后续启动进程的字符串缓冲区。
该函数使用了stdarg.h的类型和宏,在Linux(gcc编译)、Windows(gcc编译)、macOS x86-64(clang编译)环境下都能正常工作,甚至在SunOS等其他UNIX衍生系统中也稳定运行了数十年。
但在macOS arm64平台,用clang 15编译后,对str的赋值有时无法正确获取剩余参数中的第一个元素。
相关代码实现
/* global variables accessed in the function */ static char *cmd_buffer = NULL; static int buffer_size = 0; static int cmd_len = 0; static int free_len = 0; static const int init_buffer_size = 1024; /* typical call: MsCommand_push(1, "cp "); */ void MsCommand_push(unsigned nb, ...) { int new_len = 0; const char *str = NULL; char *tmp = NULL; unsigned int i = 0; va_list param; va_list param2; va_start(param, nb); va_copy(param2,param); for (i=0; i < nb; i++) { str = va_arg(param, char *); /* <--- va_arg returns garbage in first iteration! */ new_len = new_len + strlen(str); } va_end(param); if (free_len < new_len) { char *tmp = cmd_buffer; cmd_buffer = calloc(cmd_len + result, sizeof(char)); memcpy(cmd_buffer, tmp, cmd_len * sizeof(char)); buffer_size = cmd_len + result; free_len = result; } ASSERT(cmd_len > 0); tmp = cmd_buffer + cmd_len - 1; str = NULL; for (i=0; i < nb; i++) { str = va_arg(param2, char *); sprintf(tmp, "%s", str); tmp = tmp + strlen(str); } va_end(param2); cmd_len = new_len + cmd_len; free_len = free_len - new_len; } /* function called before MsCommand_push */ void MsCommand_init() { ASSERT((cmd_buffer == NULL) && (init_buffer_size > 0)); cmd_buffer = (char *)malloc(init_buffer_size); free_len = init_buffer_size - 1; cmd_len = 1; cmd_buffer[0] = '\0'; buffer_size = init_buffer_size; }
为了让问题更独立、更容易复现,我修改了代码,让错误行为在更简单的上下文里出现。
我写了如下main函数:
int main(int argc, char **argv) { extern int MsFile_dummy1(); extern void MsCommand_push(unsigned nb, ...); extern void MsCommand_init(); MsCommand_init(); MsCommand_push(1, "cp "); if (MsFile_dummy1() == 1) { return 1; } return 0; }
从main中直接调用MsCommand_push是正常工作的,但通过MsFile_dummy1()调用时就会出现异常行为。这个函数只是一个包含调用的代理:
在另一个文件中,代码如下:
int MsFile_dummy1() { MsCommand_push(1, "cp "); return 0; }
请问可能是什么问题?我该如何修复?
注:我找到过一个10年前关于这个主题的讨论,但认为它可能已经过时了。
备注:内容来源于stack exchange,提问作者dde
相关产品推荐
相关产品推荐

