c - 使用 stdargs (va_start) 的 C 程序的奇怪行为 (SEGFAULT)

标签 c malloc variadic segmentation-fault

我写了一个可变参数 C 函数,它的任务是为缓冲区分配所需的内存,然后在该缓冲区中 sprintf 给这个函数的参数。但我看到它有一种奇怪的行为。它只工作一次。如果我对该函数有两次调用,它就会出现段错误。

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

char *xsprintf(char * fmt, ...)
{
    va_list ap;
    char *part;
    char *buf;
    size_t len = strlen(fmt)+1;

    va_start(ap, fmt);
    while (part = va_arg(ap, char *))
        len += strlen(part);
    va_end(ap);

    buf = (char*) malloc(sizeof(char)*len);

    va_start(ap, fmt);
    vsprintf(buf, fmt, ap);
    va_end(ap);

    return buf;
}

int main(int argc, const char *argv[])
{
    char *b;
    b = xsprintf("my favorite fruits are: %s, %s, and %s", "coffee", "C", "oranges");
    printf("size de buf is %d\n", strlen(b)); //this works. After it, it segfaults.
    /*
    free(b);
    b = NULL;
    */
    b = xsprintf("my favorite fruits are: %s, %s, and %s", "coffee", "C", "oranges");
    printf("size de buf is %d\n", strlen(b));
    printf("%s", b);
    return 0;
}

这是这个程序的输出:

size de buf is 46
[1]    4305 segmentation fault  ./xsprintftest

我做错了什么吗?我不应该在一个函数中多次使用 va_start 吗?你有其他选择吗?非常感谢! :)

最佳答案

你应该使用 vsnprintf .使用它两次。一次使用 NULL目标/零大小找出您需要分配的缓冲区的长度,然后第二次填充缓冲区。这样,即使所有参数都不是字符串,您的函数也能正常工作。

正如所写,如果有任何非字符串参数( %d%x%f 等),它将失败。并计算 % 的数量characters 不是获取参数数量的有效方法。您的结果可能太多(如果文字 % 字符编码为 %% )或太少(如果 %*s%.*d 等宽度/精度说明符也需要参数)。

关于c - 使用 stdargs (va_start) 的 C 程序的奇怪行为 (SEGFAULT),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3397401/

相关文章:

c - 释放内存后我们如何访问指针?

c++ - 将零参数包传递给 printf

c - grep 是如何工作的?

objective-c - 将 unsinged char 数组从 objective-c 快速转换为 UnsafeMutablePointer<UInt8>

代码打印出额外的数据

c - 当 printk() 驻留的内核函数未被调用(根据 ftrace)时,为什么 printk() 会在 syslog 内部连续打印?

c - 第二次运行后带有 realloc 的函数使程序崩溃

c - c 中的内存是如何分配的,为什么两个连续的内存之间的差异总是4?

c++ - 从一个函数和某些类型说明符定义整个派生类的宏?

c++ - 将函数 f 传递给 f 类型的类模板的构造函数