va_args解析中的分段错误

时间:2011-03-17 13:27:33

标签: c malloc segmentation-fault variadic-functions

为什么下面的代码会给出EXC_BAD_ACCESS, could not access memory

int combine_strings(char **outputStr,...)
{
    va_list ap;
    char *s, *out=0;
    int len=0;

    va_start(ap,outputStr);
    while(s=va_arg(ap,char *))
    {
      len+=strlen(s);
    }
    va_end(ap);


    if(!(out=malloc(len+1)))
        exit(1);

    *outputStr=out;

    va_start(ap,outputStr);
    while(s=va_arg(ap,char *))
    {
      len=strlen(s);
      memcpy(out,s,len);
      out+=len;
    }
    va_end(ap);

    *out=0;

    return 0;
}

4 个答案:

答案 0 :(得分:8)

我不同意以前的其他海报。原始代码不会迭代相同的va_list两次。它会创建两个不同的并依次迭代它们,即使使用相同的变量来保存两个列表。

事实上,我设法正确运行了这个功能。因此,我的猜测是问题在于如何调用函数。以下是我调用它的方法,请注意尾随NULL以及output参数的设置:

#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>

// ... combine_strings() goes here...
int main()
{
  char * res;
  char * * output = &res;
  combine_strings(output, "FOO", "BAR", "BAZ", NULL);
  printf("%s\n", *output);
}

上面的代码按预期输出FOOBARBAZ

答案 1 :(得分:2)

您不能两次迭代相同的va_list。您需要使用va_copy()创建副本。

int combine_strings(char **outputStr,...)
{
    va_list ap, ap2;
    char *s, *out=0;
    int len=0;

    va_start(ap,outputStr);
    va_copy(ap2, ap);
    while(s=va_arg(ap2,char *))
    {
      len+=strlen(s);
    }
    va_end(ap2);


    if(!(out=malloc(len+1)))
        exit(1);

    *outputStr=out;

    while(s=va_arg(ap,char *))
    {
      len=strlen(s);
      memcpy(out,s,len);
      out+=len;
    }
    va_end(ap);

    *out=0;

    return 0;
}

答案 2 :(得分:2)

在一个函数中使用va_start两次很难在所有平台上运行。有关详细信息,请参阅here

可能最好使用va_copy

答案 3 :(得分:2)

回答这类问题的简单方法是在调试器中运行它。您将获得完整的堆栈跟踪,代码指针,并且您将能够查看所有变量的值。

要使用gdb,首先使用调试符号(gcc中的-g)编译程序。然后,运行它:

gdb program_name
(gdb) run

它会崩溃,你将能够看到原因。