2017-06-01 56 views
0

我有以下代碼來使用vsnprintf()附加一個緩衝區。在msvc和gcc上使用vsnprintf時出現的不同行爲

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

using namespace std; 

void MyPrintFunc(char *buffer, size_t sizeOfBuffer, const char* format, ...) 
{ 
    va_list arg; 
    va_start(arg, format); 

    vsnprintf(buffer, sizeOfBuffer, format, arg); 

    va_end(arg); 
} 

int main() 
{ 
    char buffer[1000] = { 0 }; 
    const char* abc = "abc"; 
    const char* def = "def"; 

    MyPrintFunc(buffer, 1000, "%s", abc); 
    MyPrintFunc(buffer, 1000, "%s%s", buffer, def); 
    printf("%s\n", buffer); 
    return 0; 
} 

它在Windows和Linux上給出了不同的輸出。 在Windows上(使用msvc-14.0編譯器),它給出了期望的輸出abcdef

但是在Linux上(使用gcc-5.4),它只打印輸出def

如何獲得正確的輸出?

+3

'vsnprintf'被定義爲表現得像'snprintf',保存爲參數規定通過'va_arg'列表完成。 'snprintf'具體調用語言標準,「如果在重疊的對象之間進行復制,則行爲不確定。」你的'buffer'既是目標緩衝區又是第二次調用的格式化輸入參數源,從而調用* undefined behavior *。從這個意義上說,試圖理解輸出是毫無意義的;你會在沒有存在的情況下尋找定義。 – WhozCraig

回答

1

不要使用與vsnprintf的輸出和輸入相同的緩衝區。

0

謝謝大家的意見。

我到該溶液中是如果MyPrintFunc()的用戶用它來附加緩衝器創建緩衝器的副本:

void MyPrintFunc(char *buffer, size_t sizeOfBuffer, const char* format, ...) 
{ 
    va_list arg; 
    va_list arg_copy; 

    va_start(arg, format); 
    va_copy(arg_copy, arg); 

    if (buffer == va_arg(arg, char*)) 
    { 
     char temp[strlen(buffer)]; 
     strcpy(temp, buffer); 
     MyPrintFunc(buffer, sizeOfBuffer, format, temp, va_arg(arg,char*)); 
    } 
    else 
    { 
     vsnprintf(buffer, sizeOfBuffer, format, arg_copy); 
    } 

    va_end(arg); 
    va_end(arg_copy); 
} 
相關問題