本文记录一个由错误使用StringCchVPrintf等格式化函数所导致的崩溃问题。
一. 问题描述
我们常用的格式化字符串函数有:
1 | HRESULT StringCchVPrintf( |
1 | int printf ( const char * format, ... ); |
对于如下的调用:
1 | char buf[100] = {0}; |
此时buf
中存储的并不是期望的select * from member where name like '%sjj%';
字符串。不出意外,%sjj%
处的%s
会变成乱码。
因为函数将%sjj%
中的%s
当做了字符串格式化串了,而我们又没有给最后一个参数(即可变参数)传值,根据可变参数的原理,默认会根据format参数的地址来取一个地址让%s
进行输出。
具体计算方式参考va_start
宏定义:
1 |
这个地址的内容是未知的,所以就可能出现乱码或崩溃。
二. 解决方案
要解决这个问题,我们只需要做到一点,在调用StringCchVPrintf、vsprintf、vswprintf、_vstprintf、printf
等函数时,一定不要将固定字符串传入到pszFormat
参数,如:
1 | StringCchVPrintf(szBuf, 512, "我想输出单纯的%s,我是错误的格式示范"); // 错误的 |
这个时候,单纯的%s
中的%s
已经不在单纯。
正确的做法是:
1 | StringCchVPrintf(szBuf, 512, "%s", "我想输出单纯的%s,我是正确的格式示范"); |
同理,下面的调用方式也是错误的、危险的:
1 | std::string strInfo = GetInfo(); |
文章图片带有“CSDN”水印的说明:
由于该文章和图片最初发表在我的CSDN 博客中,因此图片被 CSDN 自动添加了水印。