2017-06-01 9 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'は第2の呼び出しでターゲットバッファと書式化された入力引数ソースの両方であり、*未定義の動作*を呼び出します。それで、出力を感知しようとするのは無意味です。あなたはどこにも存在しない定義を探しているでしょう。 – 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); 
}