我想在内存中搜索当前进程的模式。我使用VirtualQuery查询内存页面以提取感兴趣的范围。问题是,在连续循环5分钟后,程序会因堆栈溢出而崩溃。进程分配的内存大小变大。
问题在于这个循环:
valid_range:
pushad
mov eax, [ebp]
mov esi, [eax] ; memory range start
mov ecx, [eax + 12] ; memory range size
xor eax, eax
loopmem:
lodsb ; this causes stackoverflow after certain time ????
dec ecx
cmp ecx, 0 ; we loop trough memory until we finish it
; reduced the code to minimum
je finish_range
jmp loopmem
finish_range:
popad
ret
答案 0 :(得分:0)
您可能正在探测为堆栈保留的页面。这可能导致分配新的堆栈页面并最终导致堆栈溢出。来自Microsoft Support:
在Microsoft Windows NT操作系统中,使用页面保护机制,硬件和软件协同工作检测到堆栈溢出。每个新的Windows NT进程都具有最大保留堆栈大小和初始提交堆栈分配。提交的内存物理分配给进程,并由页面文件支持;它是一种相对“昂贵”的资源。保留存储器是未映射到实际存储器的地址空间;它是一种相对“便宜”的资源。
随着堆栈的增长,它会从堆栈内存的已提交部分移动到保留或未提交的内存中。发生这种情况时,会发生页面错误,操作系统会将另一页内存提交到堆栈。 如果堆栈已经增长到指定的最大大小时发生页面错误,系统将报告堆栈溢出异常。
这种自动增长方法使用一个保护页面,一个保留的,未提交的内存页面,它与已提交的内存部分相邻。 当应用程序触及防护页面时,操作系统将提交该页面,下一个未提交的页面将成为新的防护页面。自动堆栈增长仅适用于防护页面,堆栈内存必须以4K增长,或者一页,增量。如果应用程序在触及保护页面之前触及另一个保留但未提交的堆栈内存页面,则会发生正常的页面错误异常并导致不可预测的行为。