va_args 解析中的分段错误

发布于 2024-10-23 13:42:07 字数 533 浏览 3 评论 0原文

为什么下面的代码给出EXC_BAD_ACCESS,无法访问内存

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;
}

Why does the code below gives 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;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

一紙繁鸢 2024-10-30 13:42:07

我不得不不同意之前其他海报的观点。原始代码不会对同一个 va_list 进行两次迭代。它创建两个不同的列表并依次迭代每个列表,即使使用相同的变量来保存两个列表也是如此。

事实上,我成功地运行了该函数。因此,我的猜测是问题在于函数的调用方式。以下是我的调用方式,请注意尾随的 NULLoutput 参数的设置:

#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

I have to disagree with the other previous posters. The original code does not iterate over the same va_list twice. It creates two different ones and iterates over each of them in turn, even though the same variable is used to hold both lists.

In fact, I managed to run the function properly. Hence, my guess is that the problem is in how the function was called. Here is how I called it, note the trailing NULL and the setup of the output parameter:

#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);
}

The code above outputs FOOBARBAZ as expected.

空城仅有旧梦在 2024-10-30 13:42:07

您不能对同一个 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;
}

You cannot iterate over the same va_list twice. You need to create a copy using 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;
}
情深已缘浅 2024-10-30 13:42:07

在一个函数中使用两次 va_start 很难在所有平台上工作。请参阅此处了解更多信息。

可能最好使用 va_copy

Using va_start twice in one function is difficult to get to work on all platforms. See here for more information.

Probably best to use va_copy.

从来不烧饼 2024-10-30 13:42:07

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

要使用gdb,首先使用调试符号(-g 在海湾合作委员会)。然后,运行它:

gdb program_name
(gdb) run

它会崩溃,您将能够明白原因。

The easy way to answer this kind of question is to run it in a debugger. You'll get a full stack trace, code pointer, and you'll be able to look at the values of all the variables.

To use gdb, first compile the program with debugging symbols (-g in gcc). Then, run it:

gdb program_name
(gdb) run

It will crash and you'll be able to see why.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文