我观察到Microsoft实现的一个有趣的问题strncat
.它接触源缓冲区之外的1个字节.请考虑以下代码:
#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);
}
Run Code Online (Sandbox Code Playgroud)
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 链接以在Microsoft Connect上发布 ; 链接到MSDN论坛上的讨论
更新5问题将在下一个VS版本中修复.旧版本没有计划修复.请参阅上面的"Microsoft Connect"链接.
我的应用程序(VC MFC)运行gflags启用Pageheap以跟踪页面堆损坏.
现在应用程序崩溃并显示此错误,我无法解释这些行(除了感觉资源的可用性)
任何人都可以了解造成应用程序崩溃的原因究竟是什么?
(info:应用程序是一个多线程的应用程序,在多处理器计算机中运行大约500个线程)
kernel32!RaiseException+53
msvcrt!_CxxThrowException+36
mfc42u!AfxThrowResourceException+19
mfc42u!AfxRegisterWndClass+ab
mfc42u!CAsyncSocket::AttachHandle+5c
mfc42u!CAsyncSocket::Socket+25
mfc42u!CAsyncSocket::Create+14
Run Code Online (Sandbox Code Playgroud) 代码中的错误
int main()
{
void *ptr = 0;
int overrun = 1;
ptr = malloc(overrun);
while(overrun++)
{
if(!ptr)
while(1) Sleep(500);
*((char*)ptr + (overrun+1)) = 'a';
printf("\n%d\n",overrun);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)从visual studio 2010的项目菜单确保构建为"Release"和"x64"(机器为x64)
启用FULL PAGE HEAP
gflags /p /enable test.exe /full
Run Code Online (Sandbox Code Playgroud)制作windbg默认调试器
E:\installed\Debugging Tools for Windows (x64)>windbg -I
Run Code Online (Sandbox Code Playgroud)在cmd
没有调试器的情况下将代码作为单独的exe运行
输出:
2
3
4
5
6
7
8
9
10
11
12
13
14
Run Code Online (Sandbox Code Playgroud)
之后看到windbg抓住腐败.而且我认为整页堆可以立即捕获损坏.
有关为什么整页堆糟透了的任何评论?