sprintf_s缓冲区太小

以下代码导致错误并杀死我的应用程序。 这是有意义的,因为缓冲区只有10个字节长,文本长度为22个字节(缓冲区溢出)。

char buffer[10]; int length = sprintf_s( buffer, 10, "1234567890.1234567890." ); 

我如何捕获此错误,以便我可以报告它而不是崩溃我的应用程序?

编辑:

阅读下面的评论后,我选择_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 

您可以使用snprintf (在Windows上也称为_snprintf )而不是sprintf_s

 #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 */ } 

这是设计的。 sprintf_s的整个点和*_s系列中的其他函数是捕获缓冲区溢出错误并将它们视为先决条件违规 。 这意味着它们并非真正意味着可以恢复。 这只是为了捕获错误 – 如果您知道字符串对于目标缓冲区来说太大, sprintf_s应该调用sprintf_s 。 在这种情况下,首先使用strlen检查并确定是否需要修剪。

这适用于VC ++,甚至比使用snprintf更安全(当然比_snprintf更安全):

 void TestString(const char* pEvil) { char buffer[100]; _snprintf_s(buffer, _TRUNCATE, "Some data: %s\n", pEvil); } 

_TRUNCATE标志表示该字符串应该被截断。 在这种forms下,缓冲区的大小实际上并未传入,(矛盾的是!)是如此安全的原因。 编译器使用模板魔术来推断缓冲区大小,这意味着它不能被错误地指定(一个令人惊讶的常见错误)。 这个技术可以应用于创建其他安全的字符串包装器,如我的博客文章中所述: https : //randomascii.wordpress.com/2013/04/03/stop-using-strncpy-already/

来自MSDN:

sprintf_s和sprintf之间的另一个主要区别是sprintf_s采用一个长度参数来指定输出缓冲区的大小(以字符为单位)。 如果缓冲区对于正在打印的文本而言太小,则将缓冲区设置为空字符串并调用无效参数处理程序。 与snprintf不同,sprintf_s保证缓冲区将以空值终止(除非缓冲区大小为零)。

理想情况下,你所写的应该正常工作。

看起来你在某种MSVC上写作?

我认为sprintf_s的MSDN文档说它断言死了,所以我不太确定你是否能以编程方式捕获它。

正如LBushkin建议的那样,使用管理字符串的类会更好。

请参阅TR24731的 6.6.1节,它是Microsoft实施的function的ISO C委员会版本。 它提供了函数set_constraint_handler()abort_constraint_handler()ignore_constraint_handler()函数。

Pavel Minaev的评论暗示微软的实施不符合TR24731提案(这是’2型技术报告’),因此您可能无法进行干预,或者您可能需要采取与TR表示应该完成。 为此,仔细检查MSDN。