2013-03-31 3 views
1

Я пытаюсь изменить размер динамически распределенного массива строк; вот код!Изменение размера массива динамических строк

void resize_array() { 
    size_t newSize = hash_array_length + 100; 
    string* newArr = new string[newSize]; 

    fill_n(hash_array,newSize,"0"); //fills arrays with zeros 

    memcpy(newArr, hash_array, hash_array_length * sizeof(string)); 

    hash_array_length = newSize; 
    delete [] hash_array; 
    hash_array = newArr; 
} 

К сожалению, он не работает и дает ошибку сегментации. любая идея почему? это в основном линейная хеш-таблица, где элемент вставлен везде, где есть 0, поэтому я использую fill_n для заполнения вновь созданного массива с помощью 0. любая помощь, пожалуйста?

+1

Не могли бы вы рассказать нам, какой язык вы используете здесь и в какой строке возникает ошибка сегментации? Благодарю. – Simon

+0

Язык, который я использую, - это C++, и я не могу определить строку, на которой возникает ошибка сегментации. Я использую dev-C++ в качестве компилятора, и я думаю, что что-то не так с отладчиком. –

+1

Не было бы проще проверить неиспользуемые записи, используя ['std :: string :: empty()'] (http://en.cppreference.com/w/cpp/string/basic_string/empty) вместо заполнения и тестирование магического значения '' 0 "'? – Blastfurnace

ответ

4
memcpy(newArr, hash_array, hash_array_length * sizeof(string)); 

Эта линия крайне опасно, станд :: строка не является простым старым типа данных, вы не можете убедиться, что тетсру может инициализировать его правильно, это может привести к непредсказуемому поведению , один из самых неприятное поведение C++ (или программирования).

Кроме того, есть лучше и безопаснее (в большинстве случаев) решения для создания динамических массива строк в C++, просто использовать вектор

//create a dynamic string array with newSize and initialize them with "0" 
//in your case, I don't think you need to initialize it with "0" 
std::vector<std::string> newArr(newSize, "0"); 

если hash_array имеет тот же тип, как newArr (std :: vector) Путем копирования это очень просто.

C++ 98

std::copy(hash_array.begin(), hash_array.end(), newArr.begin()); 

C++ 11

std::copy(std::begin(hash_array), std::end(hash_array), std::begin(newArr)); 

Лучше лечить с ++ как новый язык, он имеет слишком много вещей, которые отличаются от гр. Кроме того, существует множество достойных бесплатных IDE, таких как code :: blocks и QtCreator devC++ - почти мертвый проект.

Если вы новичок в C++, C++ primer 5 - хорошая книга для начала.

+0

будет ли это делать то же самое, что и предыдущая линия memcpy? Я действительно никогда не делал C, начал с C++. –

+0

Нет, этот код создает только динамический массив строки и инициализирует его «0». Я не знаю, как скопировать hash_array в newArr, прежде чем я узнаю тип hash_array. – StereoMatching

1

Если string на самом деле std::string (и, возможно, даже если это не так), то это сбой. Вы создаете новый массив строк, копируя старые классы строк сверху, а затем освобождая старые строки. Но если класс string содержит внутренние указатели на выделенную память, это приведет к двойному свободному, поскольку все, что вы делаете, это копирование внутренних указателей - не создание новых распределений памяти.

Подумайте об этом; Представьте, что вы имели следующий класс:

class foo 
{ 
    char* bar; 

    foo() { bar = malloc(100); } 
    ~foo() { free(bar); 
}; 

foo* ptr1 = new foo; 
foo* ptr2 = new foo; 
memcpy(ptr2, ptr1, sizeof(foo*)); 
delete ptr1; 

На данный момент, ptr2->bar указывает на ту же память, что ptr1->bar сделал, но ptr1 и память она провела освободилась

Лучшим решением было бы использовать std::vector, потому что это автоматически обрабатывает размер, и вам не нужно беспокоиться о копировании массивов вообще. Но если вы хотите оставаться с текущим подходом, вам необходимо изменить memcpy вызов следующего:

for (int i = 0; i < hash_array_length; ++i) 
{ 
    newArr[i] = hash_array[i]; 
} 

Вместо копирования памяти это будет вызывать копию конструктора класса и сделать правильную копию его содержимого ,

+0

Большое спасибо! Это кажется действительно полезным и на самом деле имеет смысл! : D –

0

Я подозреваю, что виновником является memcpy звонок. string - сложный тип, который управляет массивом символов указателями (как вы сейчас это делаете).Обычно копирование строки выполняется с помощью оператора присваивания, который для строки также копирует свой собственный массив. Но memcpy просто копирует побайтовый указатель, а delete [] также удаляет массив, управляемый строкой. Теперь в другой строке используется массив удаленных строк, который является BAAAD.

Вы можете использовать std :: copy вместо memcpy или еще лучше использовать std :: vector, который исправляет большинство проблем с динамической памятью.