2016-12-29 76 views
2

我做一個DLL在C++和我得到這個錯誤我第二次調用一個函數:調試斷言失敗的類的析構

調試斷言失敗表達式:_BLOCK_TYPE_IS_VALID(pHead-> nBlockUse)

我做了一些研究,這似乎當我delete的對象,我沒有new

這裏是我認爲的代碼失敗

class tFont 
{ 
public: 
    tFont(char chars[], __int64 cods[], int count); 
    ~tFont(); 


    int fontCount = 0; 
    char* characters = NULL; 
    long long* codes = NULL; 

    std::vector<std::pair<char,long long>> exceptions; 


    char getCharacter(long long code); 


}; 

tFont::tFont(char chars[], long long cods[], int count) 
{ 
    characters = new char[count]; 
    codes = new long long[count]; 
    fontCount = count; 

    for (int i = 0; i < count; i++) 
    { 
     characters[i] = chars[i]; 
     codes[i] = cods[i]; 
    } 


} 


tFont::~tFont() 
{ 

     delete[] characters; 
     delete[] codes; 
} 
發生

錯誤發生後,視覺工作室停在delete[] characters;

我tryied這沒有任何的運氣

if (characters != NULL) 
{ 
    delete[] characters; 
} 
if (codes != NULL) 
{ 
    delete[] codes; 
} 

我只能創建這個類的一個instace作爲靜態對象

tFont* getCapFont() 
{ 
    static tFont *capFont = NULL; 

    if (capFont == NULL) 
    { 
     char characters[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; 
     long long codes[] = { 241136, 441, 183861, 102321, 45836, 5955, 19305, 7871, 220321, 102286 }; 
     int fontCount = 10; 

     capFont = new tFont(characters, codes, fontCount); 
     pair<char, long long> e; 
     e.first = '0'; 
     e.second = 24045; 

     capFont->exceptions.push_back(e); 
    } 

    return capFont; 
} 

爲什麼叫析構函數,即使我永遠不會做delete capFont

謝謝!

EDIT2:我照「jarmod」之稱,並引發該錯誤的時刻是當這個函數結束

void analysis::singleLineTextReader(tImage img, char result[], tFont font)

我說這happend我第二次調用該函數,這是可能的當singleLineTextReader結束時調用其參數font的析構函數?其在上文

+5

只是猜測,但請參閱[3/5/0規則](http://en.cppreference.com/w/cpp/language/rule_of_three)。我也建議看看['std :: vector'](http://en.cppreference.com/w/cpp/container/vector),['std :: unique_ptr'](http://en.cppreference。 com/w/cpp/memory/unique_ptr)和['std :: shared_ptr'](http://en.cppreference.com/w/cpp/memory/shared_ptr)。 –

+0

在各種方法中添加一些調試打印語句,看看發生了什麼。這可能不是你的想法。另外,在調用delete之前,沒有必要絕對需要測試NULL,但是在調用delete之後將空指針置零是一種很好的做法(並且可以選擇在刪除它之前聲明它不是null,以便在您意外地捕獲編碼錯誤雙刪除一個指針)。 – jarmod

+2

Edit2之後:'singleLineTextReader'通過值*獲取它的參數*,這意味着它創建了一個字體的副本。該副本將包含在構造函數中創建的指針的副本,並且這些副本將在析構函數中被刪除。之後,原始字體對象將包含懸掛指針。 –

回答

2
void analysis::singleLineTextReader(tImage img, char result[], tFont font) 

注意所描述的靜態對象font通過值傳遞。你不通過一個指針。你不通過對它的引用。您通過其

所以你通過singleLineTextReader a tFont通過複製構建一個你傳遞給它的對象創建的對象。當副本的析構函數運行時,它會銷燬底層對象的成員。當你再次這樣做時,你正在銷燬已經被破壞的物體。

遵守3/5/0規則。不需要時不要複製對象。

並且不要使用new/new[]除非你別無選擇。在這裏你可以使用各種其他的東西,如矢量。

+0

謝謝!這是解決方案 我將從現在開始使用更多的指針 – Lolrapa

+0

這裏的正確教訓是少**指針**,擁有原始指針是nono – sp2danny

+1

(facepalm在「我將使用更多的指針」)改爲使用智能指針。如果除了char * characters = NULL;而不是'char * characters = NULL;'你編寫'std :: unique_ptr 個字符;'(其中默認構造爲NULL隱含)並且刪除'delete []個字符;'then(1)意外地複製副本將不再可行,並且(2)由於天真的析構函數邏輯而導致的異常安全性的缺乏簡單地消失。如果你類似地寫'std :: unique_ptr 代碼;'那麼編譯器會完全自動地爲你寫析構函數。 –