2011-10-14 124 views
1

1)爲什麼在/* test1 */塊下的代碼不會打印出任何東西,但/* test2 */下的代碼打印是否正確?C中的可變參數函數

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

回答

6

/* test 1 */下的代碼不會打印任何內容,因爲vsnprint()函數不打印到標準輸出;它只是將其輸出寫入提供的緩衝區。

這純粹是運氣,如果代碼沒有崩潰,但是,因爲該行:

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

實際上告訴calloc()分配0字節的內存。因此,我不認爲內存logbuf指向0也是如此 - 因此,不僅緩衝區零字節長,而且調用strlen()可能會導致崩潰或給出無效結果。

此外,vsnprint()的第二個參數應該是緩衝區的大小,即您爲logbuf分配的大小,而不是已經在其中的任何字符串的長度;它將限制寫入緩衝區的字節數以避免緩衝區溢出。

所以得到的一切工作,你需要改變:

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

..to ..

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

..to爲LOGBUFFERSIZE字節1項分配空間。並且還改變:

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

..to ..

vsnprintf(logbuf, LOGBUFFERSIZE, fmt, va); 

..to通過它你的緩衝區的大小和刪除無用(void)演員。並且還添加一行打印logbuf,如:

fputs(logbuf, stderr); 

之後它。

+0

謝謝。我顯然誤解了calloc和vsnprintf的正確用法。 – twfx

4

此:

vsnprintf(logbuf, strlen(logbuf)... 

永遠不會格式化任何東西,因爲logbuf全部爲零(已經由calloc分配的,所以strlen將返回零,這使得vsnprintf從來沒有格式化任何東西,因爲你告訴它打印最多零個字符

+4

即使在解決該問題之後,仍然不會打印任何內容,因爲'vsnprintf'不會打印。它將結果放入'logbuf'中,但絕不會打印'logbuf'。 –

+1

你瘋了嗎?將其更改爲malloc不是解決方案 - 現在您正在使用未初始化的內存。你需要傳遞LOGBUFFERSIZE作爲第二個參數而不是strlen(logbuf)。 –

+1

if((logbuf = malloc(LOGBUFFERSIZE))== NULL) fprintf(stderr,「內存不足\ n」); va_start(va,fmt); (void)vsnprintf(logbuf,LOGBUFFERSIZE,fmt,va); fprintf(stderr,「%s」,logbuf); va_end(va); – twfx