2014-04-21 279 views
0
char * stft (const char *fmt, ...) { 

    va_list items; 
    char *out; 
    int magic = 0; // <-- here magic? 

    va_start (items, fmt); 
    vsprintf (out, fmt, items); 
    va_end (items); 

    return out; 

} 

使用像:奇怪的行爲

char *str = stft ("%s-%s %s", a, b, c); 

這是工作的解決方案? 如果刪除未使用的「魔術」變量 - 我返回字符串後出現分段錯誤。 什麼做錯了?

$ GCC --version GCC(Debian的4.4.5-8)4.4.5

$ UNAME -a Linux的深站(擠)2.6.32-5-686#1 SMP週五5 10 08:33:48 UTC 2013 i686 GNU/Linux

+0

與問題無關,但不應該有什麼東西來初始化'out'? – guest

+0

@guest:與問題無關 - 問題恰恰在於'out'未初始化,因此發生崩潰。 –

+0

不錯的偵探。謝謝 – guest

回答

1

您正在嘗試寫入未初始化的指針out。這就是你崩潰的原因。這是非常不確定的行爲。魔法是巧合的;它不會使行爲更好地定義。

這可能是最好使用vsnprintf()

char *out = malloc(256); 
... 
vsnprintf(out, 256, fmt, items); 
... 
return out; 

或類似的東西。

你可以改善這一點。例如:

char *stft(const char *fmt, ...) 
{ 
    va_list items; 

    va_start(items, fmt); 
    int length = vsnprintf(0, 0, fmt, items); 
    va_end(items); 
    char *out = malloc(length+1); 
    if (out != 0) 
    { 
     va_start(items, fmt); 
     vsnprintf(out, length+1, fmt, items); 
     va_end(items); 
    } 

    return out; 
} 

請確保您釋放調用代碼中分配的內存。

+0

>>>確保您釋放調用代碼中分配的內存。 對於未使用免費()我想解決方案,並發現奇怪的行爲 – Deep

+0

對不起,我不明白你的意見。如果你不想讓函數分配內存,那麼你有兩種選擇。更好的選擇是傳入緩衝區('char * buffer')及其長度('size_t buflen'),然後使用這些:'vsnprintf(buffer,buflen,fmt,items)'。更糟糕的選擇是'static char buffer [256];'在函數和'vsnprintf(buffer,sizeof(buffer),fmt,items);'中。這有併發問題,並且意味着您不能兩次調用該函數,並且保留兩個格式化的字符串而不進行明確的複製。這兩個都可能有一個太短的緩衝區。 –

+0

感謝您的解決方案!現在我只對單一的stft()調用使用全局緩衝區,並且對當前的stft()上下文使用一次調用重新分配的緩衝區長度。非常感謝! – Deep