Повреждение массива символов в C ++ - PullRequest
0 голосов
/ 10 октября 2011

Я работаю над проектом, который заставляет меня хранить массив объектов, конструктор которых

Item(char* item, int itemType){
char temp[200];
    for(int i = 0; i < 200; i++){
        temp[i] = '\0';
        if(item[i] != '\0'){
            temp[i] = item[i];
        }
    }
    _item = item;
    _itemType = itemType;
    _tweetIDs = NULL;
}

Не беспокойтесь о _tweetID, это еще одна функциональная часть моей программы, не связанная с моей проблемой.

Этот массив хранится в классе:

ItemList()

Как это работает, так это то, что функциональная часть моей программы анализирует строку ввода и помещает ее в объект Item (char *, int). Вот как это добавляет строку:

int addItem(char* item, int type){
    char temp1[200];
    for(int i = 0; i < 200; i++){
        temp1[i] = '\0';
    }
    int j = 0;
    while(item[j] != '\0'){
        temp1[j] = item[j];
        j++;
    }
    _items[_size] = Item(temp1, type);
    _size++;
    return _size;
}

Где _items - это массив Item (), а _size - это поле, которое увеличивается каждый раз при добавлении Item ().

Моя проблема возникает, когда мне нужно распечатать содержимое списка.

У меня есть метод, который делает это:

void printList(){

    for(int i = 0; i < 500; i++){
        if(_items[i] != NULL){
            cout << "[" << i << "] ";
        _items[i]->printContents();
        }
    }
}

Я протестировал printContents () в конструкторе Item () и протестировал printList в методе addItem, и они оба работают при вызове внутри самого класса. Проблема возникает, когда мне нужно вызвать метод print вне тела класса.

В основном методе я создаю объект List:

List itemList;

Конструктор по умолчанию устанавливает для всех членов массива Item () значение NULL и инициализирует _size.

После добавления нескольких объектов Item () в массив (который, как я подтвердил, увеличивается с помощью отладчика), я попытался распечатать его. Когда я звоню:

itemList.printList();

Это дает мне правильное количество индексов (и строк), но массив char это просто куча мусора. Я использовал отладчик, чтобы попытаться выяснить, где это пошло не так. В методе addItem () я вызвал printList для проверки массива, и вывод из него в порядке. Затем я вызвал itemList.printList () сразу после последнего вызова addItem (), и он дал мне мусор. Между addItem () и itemList.printList () массив char потерян или что-то в этом роде.

Есть идеи, что не так? Я дам тебе больше кода, если он тебе понадобится.

Ответы [ 4 ]

2 голосов
/ 10 октября 2011

В вашем конструкторе Item вы устанавливаете, как я предполагаю, элемент _item следующим образом:

_item = item;

Это просто присваивает значение указателя местоположения, на которое указывает item, в_item.На самом деле он не копирует строку!

В следующий раз, когда вы прочитаете это место, это может быть допустимо - хотя, скорее всего, это будет мусор, как вы видите.

То, что вы ищете, - это функция типа strcpy (в качестве примечания, нет необходимости делать так много ручного копирования - просто передайте этот указатель и скопируйте его один раз - в Itemконструктор).

РЕДАКТИРОВАТЬ , чтобы ответить на ваш комментарий:

strcpy вызвал сбой вашей программы, поскольку вы используете ее в нераспределенной памяти.

Вы должны выделить память для массива, используя new[] в c ++

1 голос
/ 10 октября 2011

Обратите внимание на время жизни переменной.Если вы объявите temp1 как статический массив, то он будет немедленно уничтожен концом функции addItem .

В конце все объекты, ссылающиеся на эту область памяти, будут недействительными.

И .... Если вы хотите передать ссылку на массив, сделайте это следующим образом:*

Item(char** item, int itemType)
0 голосов
/ 10 октября 2011

Я представляю ваше определение класса Item минимально выглядит так:

class Item
{
Item(char* item, int itemType);
private:
    char *_item;
};

Ваш конструктор должен выделить память для _item, чтобы сделать копию того, что передается через конструктор.Невыполнение этого требования неизбежно приведет к проблемам с памятью и исключениям.Кроме того, вы можете использовать что-то вроде вектора char.

0 голосов
/ 10 октября 2011

В конструкторе Item вы создаете локальный массив char temp[200], копируете туда, на что указывает char * item, и затем вы больше не используете temp[200].Какой смысл делать это?

Позже вы назначаете переданный указатель члену _item.Указатель указывает на локальную переменную char temp1[200] в addItem().Когда addItem() заканчивается, temp1 уничтожается и поэтому _item в Item классе указывает на мусор.

Что вам, вероятно, нужно сделать, это выделить память статически в определении _item или динамическииспользуя new (а потом не забудьте его отпустить).Я думаю, что первое решение будет безопаснее для вас.В последнем случае вам также придется позаботиться о конструкторе копирования и операторе присвоения.Итак, вам нужно изменить _item определение с char * _item на char _item[200], а затем вы можете использовать strncpy:

Item(char* item, int itemType) {
    strncpy(_item, item, 200);
}
...