2016-10-11 78 views
7

MSDN示出了該示例代碼段爲vsnprintf_s在vsnprintf_s調用之後是否需要va_end?

// crt_vsnprintf_s.cpp 
#include <stdio.h> 
#include <wtypes.h> 

void FormatOutput(LPCSTR formatstring, ...) 
{ 
    int nSize = 0; 
    char buff[10]; 
    memset(buff, 0, sizeof(buff)); 
    va_list args; 
    va_start(args, formatstring); 
    nSize = vsnprintf_s(buff, _countof(buff), _TRUNCATE, formatstring, args); 
    printf("nSize: %d, buff: %s\n", nSize, buff); 
} 

int main() { 
    FormatOutput("%s %s", "Hi", "there"); 
    FormatOutput("%s %s", "Hi", "there!"); 
    FormatOutput("%s %s", "Hi", "there!!"); 
} 

在此示例中,va_start稱爲而不一個匹配va_end

這是在MSDN一個文檔bug,或者我們應該叫va_start之前調用vsnprintf_s,然後讓這個功能做清除(即調用va_end)我們呢?

BTW:我想上面的代碼和它的工作原理與VS2015與Update 3,但我不知道這是否只是不確定的行爲...

回答

7

va_end需要每va_start調用。從http://en.cppreference.com/w/c/variadic/va_end

如果有va_startva_copy,或者如果va_end沒有相應的調用,調用va_startva_copy回報函數之前不叫,行爲是不確定的。

你不僅需要va_end但你還需要確保之前如果va_startva_copy執行執行va_end你的函數不返回。

要回答你的問題 - 是的,這是MSDN中的文檔錯誤。

3

the MSDN page for va_arg, va_copy, va_end, va_start

所有參數後已被檢索,va_end將指針重置爲 NULL。 va_end必須在函數返回之前對每個已初始化爲 的參數列表調用va_startva_copy

所以是的,這是一個文檔錯誤。

+0

一個文檔錯誤,通過溜因爲va_end'的'的MS實現不會做所有的東西,而忽略它是「無害」。 'va_end'的存在是因爲一些平臺(不是x86)需要它來避免完全摧毀堆棧。 –

1

假設vsnprintf_s應該是類似於vsnprintf,那麼你不應該指望它來調用va_end()你:

功能​​,vfprintf()vdprintf()vsprintf()vsnprintf()等同於功能printf(),fprintf(),dprintf(),sprintf(),snprintf(),除了它們被調用 va_list而不是可變數目的參數秒。 這些函數不調用va_end宏。因爲他們調用了va_arg宏,所以在調用之後ap的值是未定義的。見stdarg(3)

(我的重點)

相關問題