2014-01-14 179 views
3

我很清楚,有這樣的無數問題,但我搜索了幾個小時,並不明白我做錯了什麼,所以我會非常感謝你的幫助。 (我是編程新手)刪除[]導致堆腐敗

我需要創建一個字典管理器作爲我家庭作業的一部分,但我似乎有刪除單詞的問題。 我收到一條錯誤消息「...觸發了一個斷點」。

人們遇到這個問題的通常答案是,這是由越界引起的堆腐敗,但我無法看到是否以及如何造成這種情況。

我已經做了類似的公交信息管理,它的工作完美,使我更加困惑...(顯然,我沒有使機制完全相同,但即使看了我以前的代碼我couldn 「T隔離問題)

我加入我相信是關注的功能,

加法功能:

void Add_Word(char**& dictionary, int& dictionary_size, char word[]) 
{ 
    char** temp = new char*[dictionary_size + 1]; // Create a new array of appropriate size. 

    int i; 
    for (i = 0; i < dictionary_size; i++) 
    { 
     temp[i] = dictionary[i]; // Copy head pointers addresses for all existing items. 
    } 
    temp[i] = new char[strlen(word)]; // Add the space for the new word, 
    temp[i][strlen(word)] = '\0'; // mark its end 

    strcpy_s(temp[i], strlen(word) + 1, word); // then copy it. 
    // I'm really not so sure about what I should put in the buffer length but 
    // strlen(word) + 1 seemed to work... I know... not good, but strlen(word) alone caused a problem. 

    if (dictionary_size > 0) 
     delete []dictionary; // Delete previous head pointers array if there are any and 
    dictionary = temp; // reset the main pointer to the address of the new one. 

    dictionary_size++; // Finally, increase dictionary_size. 
} 

的刪除功能:

void Delete_Word(char**& dictionary, int& dictionary_size, char* word) 
{ 
    // !!! This is where the crash thingy happens. 
    delete[] Search_For_Word(dictionary, dictionary_size, word); // Delete the word from the dictionary. 
    // Search_For_Word returns a pointer to the word it receives, from the dictionary. 

    char** temp = new char*[dictionary_size - 1]; // Create a new array of appropriate size. 

    int i; 
    for (i = 0; i < dictionary_size; i++) 
    { 
     if (dictionary[i][0]) 
      temp[i] = dictionary[i]; // Copy the head pointers of the existing 
      // items to the new array except for the deleted word. 
    } 

    delete[] dictionary; // Delete previous head pointers array and 
    dictionary = temp; // reset the main pointer to the address of the new one. 

    dictionary_size--; // Finally, decrease dictionary_size. 
} 

編輯:任何過分低效或明顯損壞的部分都可能是由於我弄亂了我的代碼,試圖自己弄清楚這一點(比如提到strlen的3次調用(再次感謝, kfsone ...),或者忘記爲'\ 0'+1來標記一個字符串的結尾 - 實際上,不,如果我們明白你不會告訴我我的錯誤@。@)。

至於我處理字符而不是字符串和載體的原因,請允許我引用自己:「...作爲我的作業的一部分」。我剛剛開始編程。那我想在掌握基本知識之前繼續使用更舒適的高級工具。

+5

** AHRRG!**爲什麼你要處理原始'char'指針來實現這個[tag:C++]?使用s.th.比如'std :: map ',請忘記獲取內存管理權限! –

+1

這是怎麼回事:temp [i] = new char [strlen(word)];它必須是strlen(word)+1;這就是你的腐敗發生的地方 –

+1

我意識到你將它標記爲C++,因爲你使用'new'和'delete',但是你正在做的是* C + *或* C# - *,而不是C++。我想你會搞砸堆'刪除[] Search_For_Word ...',但你的代碼看起來有多種錯誤(錯過1字符串錯誤等),你顯示對指針和C字符串的理解很差,而你不要使用C++的任何實際方面。以下兩個語句中的任何一個都會替換大部分代碼,消除錯誤並且效率更高。 'std :: vector ','std :: vector >'。 – kfsone

回答

0

該代碼現在正在工作。

這一切都是錯誤的。 在嘗試修復之前,我對動態內存的描述非常混亂。

我起初並不在意撥打3次電話,因爲它只是作業和一個非常小的程序,但我想最好是習慣以正確的方式做事... 我也放棄了我的副本顯然不太理解,贊成簡單的for循環。

// Add function. The rest is cut. 
    int word_length = strlen(word); 

    temp[i] = new char[word_length + 1]; // Added +1 here. 
    temp[i][word_length] = '\0'; /* This was correct after all. 
    the word_length index is the correct ending.*/ 

    for (int j = 0; j < word_length; j++) // copy replaced by for loop. 
     temp[i][j] = word[j]; 
    // cut 
} 

void Delete_Word(char**& dictionary, int& dictionary_size, char* word) 
{ 
    delete[] Search_For_Word(dictionary, dictionary_size, word); 
    // There was a -1 mistake here I made in order to try and fix the thing earlier. 
// No need for more, it works perfectly now. 
4

變化:

temp[i] = new char[strlen(word)] 

要:

temp[i] = new char[strlen(word)+1] 
+0

修正了這個問題,但問題一直存在 我也是:temp即使如果我正確理解了kfsone,'\ 0'也會到最後一個插槽 – user2962533

+0

10應該是'temp ['[strlen(word)** + 1 **] ='\ 0'; 應該是'temp [我] [strlen(word)] ='\ 0''(沒有'+ 1') –

2

這是C++,你爲什麼不使用的std :: string代替字符緩衝區?

如果您必須使用字符緩衝區字符串,並且strcpy_s的安全形式知道緩衝區長度必須始終是目標緩衝區的大小,那麼永遠不要使用strlen函數。在你的情況下,這是有點可以理解的,因爲你創建了strlen函數的緩衝區。但是你應該做的是將值設置爲一個變量,然後在需要緩衝區大小時使用它。另外,我認爲你的錯誤是,你正在寫temp [i] [strlen(word)] ='\ 0';但是緩衝區的實際索引從0到strlen(word)-1,所以你寫的是分配的內存之外。

3

你的代碼有幾個問題。

首先,如果要使用new[]在堆上分配C風格字符串,則必須注意終止NUL字符。

所以,如果你想從一個字符串word做一個深拷貝,那麼你必須計算出足夠的空間,考慮strlen(word) + 1:該+1是終止NUL字符。
例如: -

// Original code (wrong): 
// 
//  temp[i] = new char[strlen(word)]; 
// 
// New code: 
temp[i] = new char[strlen(word) + 1]; // consider terminating NUL (+1) 

此外,以下有明確new[] S和delete[]是你的代碼是不容易的。
現代C++,您可能想要使用方便健壯的容器類(如std::vector)和字符串類(如std::string),而不是原始C風格指針和字符串。

您可以使用std::vector<std::string>vector::push_back()方法來簡單地存儲字符串列表,以向矢量添加新字符串。無需代碼new[]delete[]strcpy_s()

複雜,如果你想深複製的字符串,你可以使用的operator=簡單自然的過載std::string,和拷貝構造函數;例如std::string temp = word;將工作得很好。