为什么下面的代码会给出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;
}
答案 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)
答案 3 :(得分:2)
回答这类问题的简单方法是在调试器中运行它。您将获得完整的堆栈跟踪,代码指针,并且您将能够查看所有变量的值。
要使用gdb,首先使用调试符号(gcc中的-g
)编译程序。然后,运行它:
gdb program_name
(gdb) run
它会崩溃,你将能够看到原因。