【问题标题】:variadic function in CC中的可变参数函数
【发布时间】:2011-10-14 02:38:55
【问题描述】:

1) 为什么/* test1 */块下的代码不打印任何东西,但/* test2 */下的代码打印正确?

2) 如何在/* test 1 */ 代码块中使用va_arg(va, char*)


void rdfDBG(int dbglevel, const char *fmt, ...) {

    va_list va;

#if 1 /* test 1 */
    char* logbuf;

    if ((logbuf = calloc(0x0, LOGBUFFERSIZE))== NULL)
        fprintf(stderr, "out of memory\n"); /* 1. Is there a better way instead of using fprintf? */

    va_start(va, fmt);
    (void) vsnprintf(logbuf, strlen(logbuf), fmt, va); /* 2. print nothing */
    va_end(va);

    free(logbuf);
#endif

#if 0 /* test 2 */
    va_start(va, fmt);
    vprintf(fmt, va); /* 2. print "pinfile pings6.txt" */
    va_end(va);
#endif


}


int ptInitialize(){

    char* pinfile;
    pinfile = "pings6.txt";

    rdfDBG(kINFO, "pinfile %s\n", pinfile);

    return 0;
}

【问题讨论】:

    标签: c variadic-functions


    【解决方案1】:

    /* test 1 */ 下的代码不打印任何内容,因为vsnprint() 函数不打印到标准输出;它只是将其输出写入提供的缓冲区。

    不过,如果代码没有崩溃,那纯属幸运,因为这行:

    if ((logbuf = calloc(0x0, LOGBUFFERSIZE))== NULL)
    

    实际上告诉calloc()分配0字节的内存。因此,我认为也不能保证logbuf 指向的内存为零——因此不仅您的缓冲区长度为零字节,而且在其上调用strlen() 可能会崩溃或给您无效的结果。

    另外,vsnprint() 的第二个参数应该是缓冲区的大小,即您为logbuf 分配的大小,而不是其中任何字符串的长度;这是为了限制写入缓冲区的字节数,以避免缓冲区溢出。

    因此,要让一切正常运行,您需要进行更改:

        if ((logbuf = calloc(0x0, LOGBUFFERSIZE))== NULL)
    

    ..到..

        if ((logbuf = calloc(1, LOGBUFFERSIZE))== NULL)
    

    ..为LOGBUFFERSIZE 字节中的一项分配空间。并且还要改变:

    (void) vsnprintf(logbuf, strlen(logbuf), fmt, va);
    

    .. 到..

    vsnprintf(logbuf, LOGBUFFERSIZE, fmt, va);
    

    ..将缓冲区的大小传递给它并删除无用的(void) 演员。并且还要加一行打印logbuf,如:

    fputs(logbuf, stderr);
    

    在它之后。

    【讨论】:

    • 谢谢。我显然误解了 calloc 和 vsnprintf 的正确用法。
    【解决方案2】:

    这个:

    vsnprintf(logbuf, strlen(logbuf)...
    

    永远不会格式化任何东西,因为logbuf 是全零(由calloc 分配,所以strlen 将返回零,这使得 vsnprintf 永远不会格式化任何东西,因为你告诉它最多打印零个字符。

    【讨论】:

    • 即使在解决了这个问题之后,您仍然不会得到任何打印,因为vsnprintf 不会打印。它将结果放入logbuf,但您从不打印logbuf
    • 你疯了吗?将其更改为 malloc 不是解决方案 - 现在您正在使用未初始化的内存。您需要将 LOGBUFFERSIZE 作为第二个参数而不是 strlen(logbuf) 传递。
    • if ((logbuf = malloc(LOGBUFFERSIZE))== NULL) fprintf(stderr, "out of memory\n"); va_start(va, fmt); (void) vsnprintf(logbuf, LOGBUFFERSIZE, fmt, va); fprintf(stderr, "%s", logbuf); va_end(va);
    • 三票赞成?真的吗?这个答案显然是不正确的。德米特里的回答是正确的。
    • 怎么错了?我会欣然承认它是不完整的,因为我现在看到代码实际上存在很多问题,但如果我说的确实有问题,我想知道是什么。
    猜你喜欢
    • 1970-01-01
    • 2023-01-31
    • 2011-02-19
    • 2010-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多