You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 09:18:04