С ++ массив символов правильно перемещает нулевой терминатор? - PullRequest
1 голос
/ 15 февраля 2012

Привет, мою проблему довольно сложно объяснить, поэтому я просто опубликую свой раздел кода здесь и объясню проблему на примере.

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

//this code is in a loop that runs until all of the big array has been copied
char* splitArray = new char[50];        
strncpy(splitArray, bigArray+startPoint, 50); //startPoint is calculated with every loop run, it marks the next point in the array for copying

//output of splitArray on the screen here

delete splitArray;
//repeat loop here

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

после более глубокого изучения я обнаружил, что на самом деле splitArray имеет размер не 50, а 64, с нулевым терминатором в 64. Поэтому, когда я копирую из bigArray в splitArray, все еще остаются14 случайных символов, оставшихся после настоящей строки, и, конечно, я не хочу их выводить.

Простым решением было бы вручную установить нулевой терминатор в splitArray на [50], но затем программа не удаляетсяснова массив.

Может кто-нибудь помочь мне найти решение для этого?Предпочтительно с некоторым примером кода, спасибо.

Ответы [ 5 ]

0 голосов
/ 15 февраля 2012

Я вижу пару проблем с вашим кодом:

  1. Если вы выделяете с помощью new [], вам нужно бесплатно с delete [] (не delete)
  2. Почему вы используете freestore? Из того, что я вижу, вы также можете использовать локальный массив.
  3. Если вы хотите сохранить 50 символов в массиве, вам нужно 51 для завершающего нулевого символа.

Вы хотели код:

while(/* condition */)
{
    // your logic

    char splitArray[51];
    strncpy(splitArray, bigArray+startPoint, 50);
    splitArray[50] = '\0';

    // do stuff with splitArray
    // no delete
}
0 голосов
/ 15 февраля 2012

Функция strncpy имеет недостаток, заключающийся в том, что она не завершает строку назначения, если строка источника содержит более 50 символов. Похоже, так и есть в вашем случае!

Если это действительно C ++, вы можете сделать это с помощью std::string splitArray(bigArray+startPoint, 50).

0 голосов
/ 15 февраля 2012

Когда вы выделяете память для splitArray, память не заполнена символами NULL, вам необходимо явно сделать это.Из-за этого ваша строка не завершается должным образом NULL.Для этого вы можете сделать char* splitArray = new char[51](); для инициализации символом NULL во время самого выделения (обратите внимание, что я выделяю 51 символ, чтобы в конце был дополнительный символ NULL).,Также обратите внимание, что вам нужно сделать delete[] splitArray;, а не delete splitArray;.

0 голосов
/ 15 февраля 2012

Достаточно просто сделать это:

char* splitArray = new char[50 + 1];        
strncpy(splitArray, bigArray+startPoint, 50);
splitArray[50] = '\0';

Я бы действительно спросил, почему вы все равно делаете это.Это намного чище:

std::string split(bigArray+startPoint, 50);

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

char const *s = split.c_str();

он будет правильно завершен нулем и будет иметь то же время жизни, что и строковый объект (т. Е. Вам не нужно free илиdelete это).


NB.Я не изменил ваш исходный код, но было бы неплохо потерять магические целочисленные литералы.

0 голосов
/ 15 февраля 2012

Как программа "не может удалить массив снова", если вы просто установите splitArray[49] = 0? Не забывайте, что массив длиной 50 индексируется от 0 до 49. splitArray[50] = 0 записывает в память вне той памяти, которая выделена для splitArray, со всеми вытекающими последствиями.

...