在调用支持可变参数格式化的函数时的一个很掩蔽问题
来源:互联网 发布:noteledge mac 编辑:程序博客网 时间:2024/05/18 03:19
很多时候我们都希望一些函数能够支持可变参数,这样的函数或是用来进行字符串的格式化,或是调用函数时函数本身支持参数的格式化(这样在调用函数之前不用另外格式化,调用的函数本身就支持参数的格式化)。比如C语言中的printf函数,MFC中的CString的Format函数。它们内部均是使用va_start、va_list、va_end实现参数的解析的。下面给出duilib中的CStdString::Format 的函数实现,简单的查看一下是如何解析的。
int CStdString::Format( LPCTSTR pstrFormat, ... ){ CStdString sFormat = pstrFormat; // Do ordinary printf replacements // NOTE: Documented max-length of _vstprintf() is 1024 TCHAR szBuffer[1025] = { 0 }; va_list argList; va_start( argList, pstrFormat ); // wvsprintf不支持浮点格式,所以换成_vstprintf int iRet = ::_vstprintf( szBuffer, sFormat, argList ); va_end( argList ); Assign( szBuffer ); return iRet;}
上面简要的说明了使用va_start、va_list、va_end实现了对可变参数格式化的支持,那其中的陷阱在什么地方呢?在日常的代码开发过程中,为了定位问题我们需要添加相关的打印信息,或打印到控制台窗口上,或是将日志写入到文件中。我们就以C语言中打印输出函数printf为例吧。该函数支持直接将字符串打印出来,也支持对可变参数的格式化输出,问题就掩藏在直接打印字符串这个功能上。大家看下面的代码会不会出问题:
char achBuf[] = {"this is a test %d"}; // 包含格式化符%dprintf(achBuf);上面的代码可以测试一下是没问题,achBuf中包含了一个%d的格式化,但是调用achBuf时,并没有传待格式化的参数,运行可能会出问题,但实际上运行时是不会报错的。那我们将字符串中的%d改为%s后,再测试一下,结果程序发生崩溃了。那为什么%d没问题,而%s就出现了崩溃呢?可能是在参数列表中可以随便找个整数值,但字符串就不太好找了。因为没有传待格式化的字符串参数,所以产生了崩溃。
上述代码只是一些测试代码,是我们人为的在待输出的字符串中加入了格式化符,在实际代码运行的过程中,一般不会出现这样的字符串中包含有格式化的情况。那在哪些个别情况下会出现呢?比如在聊天对话框中,用户可以随意的输入,也可能聊天的双方也在讨论编程的问题,就有可能出现输入包括%s的字符串了。我们可能为了定位问题,直接将用户输入的内容打印出来,调用支持可变参数格式化的函数将字符串直接打印出来,此时就可能出现崩溃。因为出现问题的场景比较少,所以这个问题非常隐蔽,很难被发现。这个问题在我们实际的代码开发过程中发生过两次,一次是重构代码发现的,一次是排查崩溃代码发现的。
这个问题对于几乎所有支持可变参数格式化的函数,都是存在的,不管是系统函数还是用户自定义函数。那这个问题该如何解决呢?可以采用规避的办法,不直接打印字符串,而是将字符串作为待格式化的参数传进去,即如下所示:
char achBuf[] = {"this is a test %s"}; // 包含格式化符%sprintf("%s", achBuf);这样就没有问题了,可以测试一下。
所以在直接打印用户输入字符串的场合,就要特别留意这个问题了。
- 在调用支持可变参数格式化的函数时的一个很掩蔽问题
- 在C语言中编写支持可变参数的函数
- 可变参数的格式化输出函数
- c/c++支持可变参数的函数
- C支持参数可变的函数
- c/c++支持可变参数的函数
- c/c++支持可变参数的函数
- c/c++支持可变参数的函数
- c/c++支持可变参数的函数
- 如何在一个可变参数函数中调用另一个可变参数函数
- 动态的调用可变参数函数
- 动态的调用可变参数函数
- 动态的调用可变参数函数
- Scala 可变参数函数的灵活调用
- 一个类似printf的可变参数函数
- C#关于静态函数与普通函数之间的调用问题,以及可变参数的使用
- 宏和函数的可变参数问题
- 黑马程序员—反射调用main方法的问题总结(涉及可变参数)(反射参数是一个数组的函数要小心)
- linux--- 配置ftp服务
- 利用Python获取天气信息
- 不错的代码
- 红白蓝三色小球排列成有序的红白蓝三色的同颜色在一起的小球组
- 关于SSH整合时要用的一些模板
- 在调用支持可变参数格式化的函数时的一个很掩蔽问题
- C++ 习题 输出日期时间--友元函数
- Light OJ 1047
- Spring BeanFactory实例化Bean的过程
- js获取url参数值
- (Java)冒泡排序
- AFNetwork 2.0在请求时报错code=-1016 和 3840
- 第一篇博文——测试一下
- 股票行情数据获取总结