#include <iostream>
#include <vector>
using namespace std;

int main()
{
    vector< vector<int> > dp(50000, vector<int>(4, -1));
    cout << dp.size();
}

这个小程序需要一秒钟时执行简单的命令行运行。但是,在一个调试器中运行时,它接管8秒。暂停调试器显示,它在摧毁一切的矢量的中间。 WTF?

注 - 的Visual Studio 2008 SP1,酷睿2 6700 CPU的RAM 2GB

补充:要澄清一下,不,我不是混淆调试和发布版本。这些结果是在同一个.exe文件,甚至没有任何重新编译其间。事实上,调试和发布之间的切换建立变化无关。

有帮助吗?

解决方案

运行在调试器改变用于一个没有更大量检查内存分配库。什么也不做,但内存分配和释放的程序是要遭受比“正常”程序等等。

修改 刚刚试过VS下运行您的程序,我得到一个调用堆栈,看起来像

ntdll.dll!_RtlpValidateHeapEntry@12()  + 0x117 bytes    
ntdll.dll!_RtlDebugFreeHeap@12()  + 0x97 bytes  
ntdll.dll!_RtlFreeHeapSlowly@12()  + 0x228bf bytes  
ntdll.dll!_RtlFreeHeap@12()  + 0x17646 bytes    
msvcr90d.dll!_free_base(void * pBlock=0x0061f6e8)  Line 109 + 0x13 bytes
msvcr90d.dll!_free_dbg_nolock(void * pUserData=0x0061f708, int nBlockUse=1)
msvcr90d.dll!_free_dbg(void * pUserData=0x0061f708, int nBlockUse=1) 
msvcr90d.dll!operator delete(void * pUserData=0x0061f708)
desc.exe!std::allocator<int>::deallocate(int * _Ptr=0x0061f708, unsigned int __formal=4)
desc.exe!std::vector<int,std::allocator<int> >::_Tidy()  Line 1134  C++

其示出了NTDLL.DLL调试功能和所使用的C运行。

其他提示

附加了调试器中运行的程序总是比没有慢。

这必须由VS挂钩到新/删除调用和做更多的检查连接时引起的 - 或运行时库使用的IsDebuggerPresent API和做事的不同在这种情况下

您可以轻松地在Visual Studio中尝试这个,开始调试 - >启动调试或者调试 - 程序>不开始调试。无需调试就像是从命令行中,具有完全相同的生成配置和可执行的。

在调试堆,当你在调试器中启动程序自动启用获取,而不是连接到一个已经运行的程序与调试器。

这本书的 高级Windows调试 的由马里奥·赫沃特和丹尼尔Pravat有一些有关Windows堆体面的信息,并且事实证明,上堆的一章是了在网站上的样章

页面281具有大约侧边栏“连接对战开始处理下调试器”:

  

当开始下的过程   调试器,堆管理器修改   所有请求创建新的堆和   更改堆创建标志,以   启用调试友好堆(除非   该_NO_DEBUG_HEAP环境   变量设置为1)。相比下,   连接到已经运行   过程,在这个过程中堆有   已经使用默认创建的   堆创建标志,而且不会有   设置调试友好的标志(除   明确地由应用程序设置)。

(也:半相关问题,其中I帐前此答案的一部分。)

这绝对HeapFree多数民众赞成放缓下来,你可以用下面的程序相同的效果。

传参数,如HEAP_NO_SERIALIZE到HeapFree也没有帮助。

#include "stdafx.h"
#include <iostream>
#include <windows.h>

using namespace std;


int _tmain(int argc, _TCHAR* argv[])
{
HANDLE heap = HeapCreate(0, 0, 0);

void** pointers = new void*[50000];

int i = 0;
for (i = 0; i < 50000; ++i)
{
    pointers[i] = HeapAlloc(heap, 0, 4 * sizeof(int));
}

cout << i;
for (i = 49999; i >= 0; --i)
{
    HeapFree(heap, 0, pointers[i]);
}

cout << "!";

delete [] pointers;

HeapDestroy(heap);
}

http://www.symantec.com/connect/articles /窗口 - 反调试参考

读取部2 “PEB!NtGlobalFlags” 和2 “堆标志”

想,这也许可以解释它...


编辑:加入溶液

在您的处理程序CREATE_PROCESS_DEBUG_EVENT,添加以下

// hack 'Load Configuration Directory' in exe header to point to a new block that specfies GlobalFlags 
IMAGE_DOS_HEADER dos_header;
ReadProcessMemory(cpdi.hProcess,cpdi.lpBaseOfImage,&dos_header,sizeof(IMAGE_DOS_HEADER),NULL);
IMAGE_OPTIONAL_HEADER32 pe_header;
ReadProcessMemory(cpdi.hProcess,(BYTE*)cpdi.lpBaseOfImage+dos_header.e_lfanew+4+sizeof(IMAGE_FILE_HEADER),&pe_header,offsetof(IMAGE_OPTIONAL_HEADER32,DataDirectory),NULL);
IMAGE_LOAD_CONFIG_DIRECTORY32 ilcd;
ZeroMemory(&ilcd,sizeof(ilcd));
ilcd.Size = 64; // not sizeof(ilcd), as 2000/XP didn't have SEHandler
ilcd.GlobalFlagsClear = 0xffffffff; // clear all flags.  this is as we don't want dbg heap
BYTE *p = (BYTE *)VirtualAllocEx(cpdi.hProcess,NULL,ilcd.Size,MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE);
WriteProcessMemory(cpdi.hProcess,p,&ilcd,ilcd.Size,NULL);
BYTE *dde = (BYTE*)cpdi.lpBaseOfImage+dos_header.e_lfanew+4+sizeof(IMAGE_FILE_HEADER)+offsetof(IMAGE_OPTIONAL_HEADER32,DataDirectory)+sizeof(IMAGE_DATA_DIRECTORY)*IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG;
IMAGE_DATA_DIRECTORY temp;
temp.VirtualAddress = p-cpdi.lpBaseOfImage;
temp.Size = ilcd.Size;
DWORD oldprotect;
VirtualProtectEx(cpdi.hProcess,dde,sizeof(temp),PAGE_READWRITE,&oldprotect);
WriteProcessMemory(cpdi.hProcess,dde,&temp,sizeof(temp),NULL);
VirtualProtectEx(cpdi.hProcess,dde,sizeof(temp),oldprotect,&oldprotect);

对,WTF确实

您知道您的编译器将通过内联他们优化了大量的函数调用,然后进一步优化代码中有排除任何东西,实际上并没有做任何事情,这在为int的载体的情况下将意味着:几乎也不是很多。

在调试模式下,内联不导通,因为这将使得调试可怕。

这是真的有多快C ++代码可以是一个很好的例子。

8秒??我试图在调试模式下是相同的。不超过半秒,我猜。你确定它的析构函数?

FYI。的Visual Studio 2008 SP1,酷睿2 6700 CPU的RAM 2GB。

是没有意义的我 - 在正常构造附加调试器来随机二进制应该大多只是陷阱断点中断(INT ASM 3等)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top