Ste*_*rst 10 c error-handling printf tr24731
以下代码导致错误并导致我的应用程序死亡.这是有道理的,因为缓冲区只有10个字节长,文本长度为22个字节(缓冲区溢出).
char buffer[10];
int length = sprintf_s( buffer, 10, "1234567890.1234567890." );
Run Code Online (Sandbox Code Playgroud)
我如何捕获此错误,以便我可以报告它而不是崩溃我的应用程序?
编辑:
阅读下面的评论后,我选择_snprintf_s.如果它返回-1值,则缓冲区未更新.
length = _snprintf_s( buffer, 10, 9, "123456789" );
printf( "1) Length=%d\n", length ); // Length == 9
length = _snprintf_s( buffer, 10, 9, "1234567890.1234567890." );
printf( "2) Length=%d\n", length ); // Length == -1
length = _snprintf_s( buffer, 10, 10, "1234567890.1234567890." );
printf( "3) Length=%d\n", length ); // Crash, it needs room for the NULL char
Run Code Online (Sandbox Code Playgroud)
Pav*_*aev 16
这是设计的.该系列的全部内容sprintf_s和其他功能*_s是捕获缓冲区溢出错误并将其视为违反前提条件.这意味着它们并非真正意味着可以恢复.这只是为了捕获错误 - sprintf_s如果您知道字符串对于目标缓冲区来说太大,则不应该调用.在这种情况下,strlen首先使用检查并确定是否需要修剪.
而不是sprintf_s,你可以使用snprintf(也就是_snprintf在Windows上).
#ifdef WIN32
#define snprintf _snprintf
#endif
char buffer[10];
int length = snprintf( buffer, 10, "1234567890.1234567890." );
// unix snprintf returns length output would actually require;
// windows _snprintf returns actual output length if output fits, else negative
if (length >= sizeof(buffer) || length<0)
{
/* error handling */
}
Run Code Online (Sandbox Code Playgroud)
这适用于VC++,甚至比使用snprintf更安全(当然比_snprintf更安全):
void TestString(const char* pEvil)
{
char buffer[100];
_snprintf_s(buffer, _TRUNCATE, "Some data: %s\n", pEvil);
}
Run Code Online (Sandbox Code Playgroud)
_TRUNCATE标志表示该字符串应该被截断.在这种形式下,缓冲区的大小实际上并没有传入,(矛盾的是!)是它如此安全的原因.编译器使用模板魔术来推断缓冲区大小,这意味着它不能被错误地指定(一个令人惊讶的常见错误).这个技术可以应用于创建其他安全字符串包装器,如我的博客文章中所述:https: //randomascii.wordpress.com/2013/04/03/stop-using-strncpy-already/
| 归档时间: |
|
| 查看次数: |
30954 次 |
| 最近记录: |