Ошибка подтверждения отладки - удалить вызов по указателю на символ - PullRequest
1 голос
/ 07 августа 2010

Так что я решил немного поизучаться в C ++.

Когда я вызываю функцию удаления для указателя на простой класс, который я создал, меня приветствует Debug Assertion Failure -Expression:_BLOCK_TYPE_IS_VALID(pHead->nBlockUse). Я предполагаю, что это потому, что я неправильно обработал строку и, таким образом, вызвал повреждение памяти.

Я создал базовый класс, [I] animal [/ I], для которого определена строка, которую можно установить с помощью функции.

// name
char * ptrName;

animal::animal(char * name)
{
 this->SetName(name);
};

animal::~animal()
{
 delete [] ptrName;
}

void animal::SetName(char * name)
{
 ptrName = name;
};

При использовании вышеуказанного класса, как показано ниже, возникает ошибка. Я пробовал и delete ptrName, и delete [] ptrName, но безрезультатно.

animal * cat = new animal("Optimus Prime");
delete cat;

Чего мне не хватает?

Ответы [ 5 ]

2 голосов
/ 07 августа 2010

Проблема в том, что в функции setName вы просто назначаете имя ptrName.В этом примере имя является указателем строки типа const, который вы не можете удалить (он не размещен в куче).Чтобы избежать этой ошибки, вы можете либо использовать std :: string в классе, либо выделить новый символ в конструкторе класса animal и присвоить ему указатель.Затем в деструкторе вы можете удалить массив.

2 голосов
/ 07 августа 2010

Строка "Optimus Prime" не была выделена динамически, поэтому неправильно вызывать delete для нее.

2 голосов
/ 07 августа 2010

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

1 голос
/ 07 августа 2010

Так что я решил немного поучаствовать в этом C ++.

Тогда сделайте себе одолжение и используйте C ++ right .Это можно было бы использовать std::string:

// name
std::string name_;

animal::animal(const std::string& name)
  : name_(name)
{
}

//animal::~animal() // not needed any longer

//note: copying also automatically taken care of by std::string
//animal(const animal&)
//animal& operator=(const animal&)

void animal::SetName(const std::string& name)
{
 name_ = name;
}

Взгляните на Полное руководство и список книг C ++ .Я бы порекомендовал Ускоренный C ++ .Это идет с крутой кривой обучения, но так как вы уже немного знаете C ++, это 250 страниц, которые могут поставить вас на правильный путь.

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

1 голос
/ 07 августа 2010

Кто владеет вашей строкой?

Например, когда вы создаете своего нового животного, вы передаете строковый литерал - это не ваше освобождение.

Вы должны избегать использования char * и использовать вместо него std :: string.

Если вам нужно использовать char *, подумайте о владении.Например, один из вариантов - взять копию строки (используя strdup) и владеть ею.Таким образом, вы не можете застрять со странными ошибками вроде этого

char* szFoo = strdup("my string");
{
  animal a(szFoo);
}
// At this point szFoo has been deleted by the destructor of a
// and bad things will start to happen here.
printf("The value of my string %s",szFoo);
...