2011-03-26 48 views
-1
class SimpleVariant 
{ 
public: 
    SimpleVariant() { /*...*/ }; 
    // ... 
}; 


struct VariantBlock 
{ 
    int nRows, nCols; 
    vector<SimpleVariant> theData; 
}; 



void dumbFunction(VariantBlock& theBlock, int nRows, int nCols) 
{ 
    // ... 
    cout << "theBlock.nRows= " << theBlock.nRows 
     << ", theBlock.nCols= " << theBlock.nCols 
     << ", theBlock.theData.size() " << theBlock.theData.size(); 

    theBlock.theData.resize(nRows * nCols); 
     // throws Access Violation Exception 

    // ... 
} 

輸出返回nRows = 61,nCols = 5,size()= 0,這正是它應該在那一點上,在引發訪問衝突異常之前。Soul-crushing C++ std :: vector :: resize()訪問衝突錯誤

我正在使用MSVC6,這顯然不是最佳的,但在這一點上沒有選擇。

+0

你在'SimpleVariant'中有什麼類型的成員?你是否爲'SimpleVariant'聲明瞭複製構造函數和/或複製賦值運算符?如果是這樣,他們做什麼?您發佈的代碼沒有任何明顯的錯誤,儘管我最近沒有使用VC6的經驗。 – 2011-03-26 05:18:21

+0

我沒有定義它們。 – Doug 2011-03-26 05:19:36

+2

這可能是壞的複製行爲,正如詹姆斯指出的那樣,但它也可能是程序中其他地方的內存破壞。 – templatetypedef 2011-03-26 05:20:46

回答

2

我最近不得不升級一些最初爲Visual C++ 6編寫的代碼。該代碼有問題,因爲VC++ 6沒有處理可以正確綁定到引用的東西。這是在黑暗中拍攝的東西,但你是否傳遞const VariantBlockdumbFunction?在C++規則下,這將是非法的,但我強烈懷疑VC++ 6會出錯。

另一種可能性是某種運行時不匹配。如果(1)VariantBlock分配在一個模塊中,並且(2)dumbFunction來自不同的模塊,則(3)它們用不同的設置編譯,可能編譯器的版本不同,那麼您將看到這種行爲(resize()分配新的內存,將所有內容複製到它,然後去釋放舊的內存,除了舊的內存分配在不同的運行時,所以程序barfs)。

總之,您發佈的代碼非常好。還有其他事情正在發生。

1

我想你在錯誤發生之前做了一些錯誤。一個std::vector::resize操作將要求記憶,並且堆是腐敗的一個容易的受害者。未定義行爲的壞處在於,在錯誤發生後(即「可能發生的任何事情」包括「無」),症狀可以變爲可見的一百萬條執行指令。

我們有一個「調試內存管理器」,重新定義了全球分配器和可以爲腐敗做了很多檢查:

  1. 初始化分配的內存與非明顯的位模式(這是爲了發現問題時,有人使用未初始化的內存,顯然代碼工作發現零)
  2. 添加一些「安全區」之前,每個存儲塊後和刪除檢查,它沒有被覆蓋(這是緩衝區溢出檢測)
  3. 填充內存時具有不同的釋放特定模式(這是爲了嘗試ca TCH讀取後刪除錯誤)
  4. 重複利用存儲塊和重新分配或對全球驗證檢查,被刪除的記憶模式仍然存在(這是趕上寫後刪除錯誤)
  5. 標記每一塊與__FILE__/__LINE__信息來檢測誰泄漏了內存泄漏,並能夠告訴誰使用刪除後損壞的塊。

此外,我們還有一個內存檢查例程,可根據需要遍歷所有內存塊並檢查一致性(通常我們只在分配/取消分配時執行檢查)。我們也可以在絕望的情況下注銷所有內存分配/釋放的完整列表。

對於第(5)點不幸的是C++語法很難測試,所以我們實際上不使用new,而是使用xnew宏,這個宏最終會擴展到放置分配;這也意味着我們不能測量標準庫中分配的內存塊(然而,我們存儲了在庫中分配之前在程序中進行了分配的最後一個源代碼行是什麼)。

1

我是OP。

問題是來自調用函數的內存損壞。