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

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

この小さなプログラムは、コマンド ラインから単純に実行すると、実行に数秒かかります。ただし、デバッガーで実行すると、8 秒以上かかります。デバッガーを一時停止すると、デバッガーがこれらすべてのベクターを破棄している最中であることがわかります。なんてこと?

注 - Visual Studio 2008 SP1、Core 2 Duo 6700 CPU、2 GB の RAM。

追加:明確にするために、いいえ、デバッグ ビルドとリリース ビルドを混同していません。これらの結果は 1 つの同じ .exe にあり、途中で再コンパイルすることさえありません。実際、デバッグ ビルドとリリース ビルドを切り替えても何も変わりません。

4

8 に答える 8

3

デバッガーで既に実行中のプログラムに接続するのではなく、デバッガーでプログラムを起動すると、デバッグヒープが自動的に有効になります。

MarioHewardtとDanielPravatによる「 AdvancedWindowsDebugging」という本には、Windowsヒープに関する適切な情報があり、ヒープに関する章がサンプルの章としてWebサイトに掲載されていることがわかりました。

ページ281には、「デバッガーでのプロセスの接続と開始」に関するサイドバーがあります。

デバッガーでプロセスを開始すると、ヒープマネージャーはすべての要求を変更して新しいヒープを作成し、ヒープ作成フラグを変更してデバッグに適したヒープを有効にします(_NO_DEBUG_HEAP環境変数が1に設定されている場合を除く)。比較すると、すでに実行中のプロセスにアタッチすると、プロセス内のヒープはデフォルトのヒープ作成フラグを使用してすでに作成されており、デバッグに適したフラグは設定されません(アプリケーションによって明示的に設定されていない場合)。

(また、私が以前にこの回答の一部を投稿した、半関連の質問。)

于 2009-02-11T03:05:12.040 に答える
2

これを遅くしているのは間違いなく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);
}
于 2009-02-10T13:28:30.567 に答える
1

http://www.symantec.com/connect/articles/windows-anti-debug-reference

セクション 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);
于 2010-03-27T03:08:18.970 に答える
0

8秒?? デバッグモードで同じことを試しました。私が推測する0.5秒以上ではありません。デストラクタだと確信していますか?

ご参考までに。Visual Studio 2008 SP1、Core 2 Duo 6700 CPU、2 GB の RAM。

于 2009-02-10T14:34:42.593 に答える
-1

私には意味がありません-通常の構成でデバッガーをランダムなバイナリに接続すると、ほとんどの場合、ブレークポイント割り込み(asm int 3など)をトラップするだけです。

于 2009-02-10T13:26:00.980 に答える