Visual Studio 2019中va_start崩溃及指针使用差异问题咨询
Visual Studio 2019中va_start崩溃及指针使用差异问题咨询
嘿,我来帮你拆解下这个崩溃问题的根源,其实就是va_start的使用规则被打破了,咱们一步步捋清楚:
先把你的测试代码贴出来方便对照:
#include <Windows.h> #include <tchar.h> #include <atlstr.h> void output_ok(int iIndex, const TCHAR* szFormat, ...) { TCHAR pBuf[256] = { 0 }; va_list pArgs; va_start(pArgs, szFormat); _vstprintf(pBuf, szFormat, pArgs); va_end(pArgs); } void output_crash(int iIndex, const TCHAR* szFormat, ...) { const TCHAR* fmt = szFormat; TCHAR pBuf[256] = { 0 }; va_list pArgs; va_start(pArgs, fmt); // 这里就是崩溃的核心原因 _vstprintf(pBuf, fmt, pArgs); va_end(pArgs); } int main() { CString OpenGLVersion("4.6.0"); // output_ok(0, _T("OpenGL:%s"), OpenGLVersion); output_crash(0, _T("OpenGL:%s"), OpenGLVersion); }
问题本质分析
va_start这个宏的工作逻辑,完全依赖函数的最后一个命名参数的内存位置——编译器需要通过这个参数的栈地址,精准计算出后续可变参数在栈上的起始位置。
- 在
output_ok里,你传给va_start的szFormat是函数的最后一个固定命名参数,编译器能准确找到它的栈位置,自然可以正确定位可变参数的起始地址,所以运行一切正常。 - 但在
output_crash里,你把szFormat赋值给了局部变量fmt,再把fmt传给va_start。这时候fmt是函数内部的局部变量,它的地址和原参数szFormat的栈位置完全不同,va_start会基于错误的地址去寻找可变参数,结果就是访问了非法内存,直接触发崩溃。
修复方法
非常简单,直接使用函数的原始命名参数作为va_start的第二个参数即可,不要用局部变量替代:
void output_crash_fixed(int iIndex, const TCHAR* szFormat, ...) { TCHAR pBuf[256] = { 0 }; va_list pArgs; va_start(pArgs, szFormat); // 回归正确用法,用函数的原始固定参数 _vstprintf(pBuf, szFormat, pArgs); va_end(pArgs); }
额外补充:C和C++标准都明确规定,va_start的第二个参数必须是函数的最后一个命名参数,任何偏离这个规则的用法都属于未定义行为,不同编译器可能表现不同,但崩溃是最常见的结果。
内容来源于stack exchange
相关产品推荐
相关产品推荐

