#include <stdio.h> #include <stdlib.h> #include <memory.h> #include <string.h> void main() { char dstBuf[1024]; char* src = malloc(112); memset(src,'a',112); dstBuf[0] = 0; strncat(dstBuf,src,112); }
strncat在112字节块后读取1个字节.因此,如果您不幸在无效页面边界上进行分配,则应用程序崩溃.大型应用程序可能会在这些地方间歇性地崩溃. (请注意,可以使用gflags PageHeap设置模拟此类条件;块大小必须能够被指针大小整除才能正确对齐.)
这是预期的行为还是错误?任何确认的链接? (我阅读了strncat的几个描述,但它们可以通过两种方式解释,具体取决于你的初始思路……)
更新(回答有关证据的问题):
如果从上面的文字中不清楚,我道歉,但这是一个实验性的事实.我在strncat读取地址src srcBufSize的应用程序中观察到间歇性崩溃.在这个小例子中,gflags PageHeap在崩溃时运行一致(100%).所以据我所知,证据非常可靠.
Update2(关于编译器的信息)
MS Visual Studio 2005版本8.0.50727.867.
构建平台:64位版本(32位无repro).
用于重现崩溃的操作系统:Windows Server 2008 R2.
更新3此问题还使用MS Visual Studio 2012 11.0.50727.1中内置的二进制文件重现
更新4 Link to issue on Microsoft Connect; link to discussion on MSDN Forums
更新5问题将在下一个VS版本中修复.旧版本没有计划修复.请参阅上面的“Microsoft Connect”链接.
strncat
声明:
src – pointer to the null-terminated byte string to copy from
因此,实现可以假设src输入参数实际上是NUL终止的,即使它比计数字符长.
为进一步确认,Microsoft’s own documentation规定:
strSource
Null-terminated source string.
另一方面,actual C standard表示:
The
strncat
function appends not more thann
characters (a null character and
characters that follow it are not appended) from the array pointed to bys2
to the end of
the string pointed to bys1
.正如下面的注释中所指出的,这将第二个参数s2标识为数组而不是以NUL结尾的字符串.然而,对于原始问题,这仍然是模棱两可的,因为该文档描述了对s1的最终影响,而不是从s2读取时函数的行为.