2012-03-22 3 views
0

Я пишу программу на C++, которая хранит строки в массиве строк, когда массив заполнен. Я изменяю размер массива, чтобы освободить место для большего количества элементов, используя приведенный ниже код. Но иногда (не всегда) он падает с «delete [] temp;» и я не знаю, почему и как это исправить. Пожалуйста помоги.C++ delete [] crashes

Я много искал, но не мог найти ответ нигде. Когда я отлаживаю, он говорит «недопустимый указатель», но как он может быть недействительным, когда я хранил данные там раньше и еще не освобождал его?

Это мой код:

if(item_cnt >= (arr_size - 1)) 
{ 
    int oldsize = arr_size; 
    string * temp; 
    arr_size *= 2; 
    temp = arr; 
    arr = new string [arr_size]; 
    memcpy(arr, temp, oldsize * sizeof(temp)); 
    delete[] temp; 
} 
+2

Некоторые моменты стиля: вы должны использовать 'std :: copy', а не' memcpy'. И вы не должны заниматься ручным управлением памятью ('new',' delete' и т. Д.), Вы должны использовать класс контейнера, чтобы обрабатывать все это автоматически. –

+3

'memcpy (arr, temp, oldsize * sizeof (temp));' - Не должно быть 'sizeof (* temp)'? (да, хотя, конечно, memcpy неправильно для начала) –

+2

Это плохо ... Не используйте memcpy для строк. Используйте 'string myString (toBeCopied);' .. см. Здесь: http://anaturb.net/C/string_exapm.htm –

ответ

0

Ваш массив должен быть действительно

vector<string> 

Это рекомендуемый способ реализации массивов динамического размера. Используя вектор, вы избегаете необходимости перераспределять/копировать материал вручную и избегать проблем, подобных тем, которые у вас есть.

+1

Почему? Объяснение поможет. –

-1

Смешивание старого стиля и операций в новом стиле памяти - это всегда плохая идея ... здесь вы используете memcpy и new/delete. иметь в виду, что delete[] также вызывает dtor для каждого элемента массива ...

Edit: т е р -> dtor

НТН

Марио

+0

Да, извините! вы правы! –

5

Если вы абсолютно не должны придерживаться ваш текущий подход, я бы рекомендовал использовать вектор для хранения ваших строк. Он будет управлять всей памятью для вас.

Вот пример:

#include <vector> 
#include <string> 
int main() 
{ 
    std::vector<std::string> arrayOfStrings; 

    arrayOfStrings.push_back("Hello World!"); // To Add Items 
    string value = arrayOfString.at(<some index>); // To Retrieve an Item you can also use the [] operator instead of the at method 

    return 0; 
} 
+0

Примечание: если по какой-то причине вам нужно указать на массив, вы все равно можете использовать вектор и передать '& arrayOfStrings [0]', где вам нужен указатель. – cHao

+0

На самом деле это моя домашняя работа (да, я знаю, это можно назвать обманом, но я действительно не мог найти причину поведения, которое я описал), и мне не разрешено использовать векторы здесь. Но спасибо за подсказку в любом случае – Dalibor

1

memcpy находится в корне проблемы. все говорят «не используют», но позвольте мне объяснить, почему это плохая идея.

Прежде всего, что такое строка C++ и как она делает свою магию? Это в основном массив символов переменной длины, и он достигает этого навыка, удерживая указатель внутри каждого строкового объекта, который указывает на память, выделенную для хранения этих символов. По мере того как строка растет или сжимается, эта память перераспределяется. Копировать строки правильно предполагает создание «глубокой копии» содержимого.

Теперь к коду:

arr = new string [arr_size]; 

Это создает массив пустых строк объектов. Поскольку они пусты, внутренние указатели обычно равны нулю.

memcpy(arr, temp, oldsize * sizeof(temp)); 

Здесь происходят плохие вещи. На самом деле это не создает копии исходных строк, а просто переписывает внутреннее представление. Таким образом, как старые, так и новые строки указывают на то же персональные данные. Теперь действительно винта вещи, это происходит:

delete[] temp; 

Удаляет таяли старые строки, но это также освобождает память символов, что они используют.Поэтому наши «новые» копии этих строк указывают на память, которая фактически была освобождена. Теперь у нас есть автомобильная авария: персональные данные могут быть повторно использованы для чего угодно, и когда мы снова попытаемся удалить строки, операционная система, мы надеемся, заметим, что вы пытаетесь освободить память, которая не были выделены.