我已经使用va_list通过https://devblogs.microsoft.com/oldnewthing/20131114-00/?p=2663链接查找潜在的陷阱
并且在同一链接的代码段下面指定不要以所示方式使用va_list,因为va_list不可直接复制。
BOOL FormatWithFallbackLanguage(
DWORD dwMessageId, PCTSTR pszBuffer, SIZE_T cchBuffer, va_list ap)
{
va_list apOriginal = ap;
// Format from the user's preferred language.
DWORD cchResult = FormatMessage(
FORMAT_MESSAGE_FROM_HMODULE,
g_hinst, dwMessageId, g_preferredLangId,
pszBuffer, cchBuffer, &ap);
// If that didn't work, then use the fallback language.
if (cchResult == 0) {
cchResult = FormatMessage(
FORMAT_MESSAGE_FROM_HMODULE,
g_hinst, dwMessageId, g_fallbackLangId,
pszBuffer, cchBuffer, &apOriginal);
}
return cchResult != 0;
}
链接中的文章建议针对上述编码方案使用va_copy。但是在Windows的头文件stdarg.h中,va_copy似乎没有做任何事情
#define va_copy(destination, source) ((destination) = (source))
我的问题是,在Windows中将va_copy用于va_list是否安全?如果是,为什么,如果不是,那么前进的方向是什么?
最佳答案
您不应该向内看香肠的制作方法。 :-)
好的,现在您已经看过了。您已经看到Windows并不是那些复杂的调用约定要求在va_list
中分配内存的平台之一。事实证明,您实际上不需要使用va_copy
而不是简单的赋值,并且va_end
实际上不执行任何操作。不好你不应该看的现在您必须忘记所有这些。
因为明天一切都会改变。新的库或编译器优化逻辑的更新,或者谁知道什么,突然需要va_copy
,va_end
可以防止内存泄漏,而您的内knowledge知识突然变成了危险的错误。
该标准说,您必须使用va_copy
复制va_list
。该标准说,您必须为每个已初始化的va_end
调用va_list
,然后调用。而且您必须这样做。因为您不知道没有业务往来的地方就无法知道平台上不需要它。
标准库不必遵守这些规则。由于它仅需要在自己的环境中工作,因此它可以完全了解其平台及其内部的知识。如果有什么变化,维护标准库的优秀人员将意识到这一点,他们将确保新版本与平台上其编译器的新版本兼容
就是这样:实现将保证如果您遵守规则,一切都会奏效。有了这些规则,以便实现者可以处理其平台的特殊性,从而使编译器可以挤出尽可能多的优化周期。
有时候,偷工减料和违反规则似乎无济于事,至少现在和现在都不会。但是不要屈服于这种诱惑。因为这样做会在代码中留下定时炸弹,该炸弹迟早会消失。