2011-03-31 10 views
2

我是一個大型商業程序的開發人員,我試圖追查一個特定的C++內存泄漏。我想使用Visual Studio來搜索我的進程的整個有效地址空間,但我看不到如何有效地執行此搜索。如何從Visual Studio調試器執行所有進程內存的高級搜索?

我知道了.S命令文檔here的,但它沒有做什麼,我需要。例如,我100%肯定地址0xfdfd240包含值0x0f0e34a8。我可以成功地使用.S命令像這樣的地址附近搜索:

.s -d 0x0fdfd200 L256000000 0x0f0e34a8 
Found match at 
0xfdfd240 

但我的計劃已經已經給我留下的記憶很多小非contiguious部分很多小的撥款。如果我背了幾千字節的搜索命令失敗:

.s -d 0x0fd00000 L256000000 0x0f0e34a8 
Memory location could not be read. Please specify a valid memory location. 

而且它也出現了搜索命令不會嘗試向前搜索任何更多的時候發現它的第一個錯誤的地址,即使有有效超越它的地址

.s -d 0x0f000000 L256000000 0x0f0e34a8 
No match was found 

我隱約地感到有一種方式來問窗口什麼內存範圍是適用於一個給定的過程,所以我考慮寫一個小程序一次性收穫的信息,然後自動執行一系列的搜索命令到立即窗口...但似乎有人必須已經處理過這個,並且一定做了更聰明的事情。

另外,我可以提取正在運行的進程的轉儲文件,因此,如果任何人都可以推薦第三方工具來養活轉儲到具有應當制定以及強大的搜索功能。

有什麼建議嗎?

編輯:我在VS2008SP1和VS2010SP1中看到了這種行爲。

+0

看到非明顯的內存泄漏,你需要購買像淨化內存泄漏分析程序。 – 2011-03-31 01:47:09

回答

1

在做任何超出簡單的調試,我發現很多時候WinDbg中(適用於Windows調試工具的一部分)具有更好的性能。

而且你甚至不需要從WinDbg進行所有的調試。如果你在VS做你的事情,然後想搜索內存(或者做其他VS中不容易的事情),請轉到Debug - > Save Dump As ...確保選擇「Minidump with Heap」文件類型。

這將創建一個完整的過程快照文件。把它加載到WinDbg中,現在你可以使用許多很酷的命令。爲了便於訪問文檔,您始終可以在命令窗口中鍵入「.hh」。所有命令列在調試器 - >調試器參考 - >調試器命令下。

你想要的是S(搜索存儲器)

+0

感謝您將我指向WinDbg,它的搜索命令的行爲如我所願。 – Jaqenn 2011-03-31 14:08:36

3

下面是一個小工具,用於在目標進程中查找內存塊,在塊中搜索一個模式,並打印出找到該模式的地址。現在它相當簡單 - 純粹是命令行,期望您提供目標進程的PID,只接受命令行中單個字符串的模式。搜索部分應該是相當健壯的,所以它主要是一個非常薄弱的​​用戶界面 - 儘管如此,只要你想要的模式是你可以在命令行中輸入的字符串,它就可以正常工作。如果你想包含不可打印的字符,那麼很容易在幾年前寫過的translator中添加,這會讓你在命令行上使用C風格的轉義序列。


跳過裝東西等可執行該進程/ dll的代碼塊。


#include <iostream> 
#include <vector> 
#include <string> 
#include <windows.h> 
#include <algorithm> 
#include <iterator> 

template <class outIter> 
void find_locs(HANDLE process, std::string const &pattern, outIter output) { 

    unsigned char *p = NULL; 
    MEMORY_BASIC_INFORMATION info; 

    // VirtualQueryEx does the hard part, telling use about each 
    // block in the target process. 

    for (p = NULL; 
     VirtualQueryEx(process, p, &info, sizeof(info)) == sizeof(info); 
     p += info.RegionSize) 
    { 
     // buffer to hold copies of memory blocks from the target 
     std::vector<char> buffer; 
     std::vector<char>::iterator pos; 

     // We only want committed memory that's mapped or private -- 
     // screens out things like the code in the target process. 
     // 
     if (info.State == MEM_COMMIT && 
      (info.Type == MEM_MAPPED || info.Type == MEM_PRIVATE)) 
     {    
      DWORD bytes_read; 

      // copy block from target to our buffer, search for pattern: 
      buffer.resize(info.RegionSize); 
      ReadProcessMemory(process, p, &buffer[0], info.RegionSize, &bytes_read); 
      buffer.resize(bytes_read); 

      // find all occurrences of pattern in buffer: 
      for (pos = buffer.begin(); 
       buffer.end()!=(pos=std::search(pos, buffer.end(), pattern.begin(), pattern.end())); 
       ++pos) 
      { 
       // record each address in target where pattern was found: 
       *output++ = p+(pos-buffer.begin()); 
      } 
     } 
    } 
} 

int main(int argc, char **argv) { 
    if (argc != 3) { 
     fprintf(stderr, "Usage: %s <process ID> <pattern>", argv[0]); 
     return 1; 
    } 

    // Read the target PID and search pattern: 
    int pid; 
    sscanf(argv[1], "%i", &pid); 
    std::string pattern(argv[2]); 

    // Open the target process with rights to read its information and memory: 
    HANDLE process = OpenProcess( 
     PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, 
     false, 
     pid); 

    // Find the locations, and write them to standard output, one per line: 
    find_locs(process, pattern, 
     std::ostream_iterator<void *>(std::cout, "\n")); 

    return 0; 
} 
相關問題