Местоположение чтения нарушения доступа 0x00000000 cstrings

Прочитав другие вопросы о стеке, я знаю, что эта ошибка означает, что я пытаюсь разыменовать нулевой указатель. Однако я не могу понять, где мой код разыменовывает нулевой указатель. Я пытаюсь установить для char* (cstring) ненулевое значение, но получаю сообщение об ошибке нарушения прав доступа. Вот код:

void Data::setName(char const * const name)
{
    if (this->name)
        delete[] this->name;

    this->name = new char[strlen(name) + 1];    // This is where my code breaks in debug mode
    strcpy(this->name, name);
}

name — это переменная типа char*, которая инициализируется значением null. setName вызывается перегруженным оператором присваивания:

Data& Data::operator=(const Data& data2)
{
    //if it is a self copy, don't do anything
    if (this == &data2)
        return *this;

    else
    {
        setName(data2.name);    // Here is the call to setName
        return *this;
    }
}

P.S. Ради бога, пожалуйста, не говорите мне, что я не должен использовать cstrings! Я знаю, что std::string лучше, но это домашнее задание, требующее cstrings.


person chillpenguin    schedule 08.06.2014    source источник
comment
Пожалуйста, опубликуйте весь свой класс, а также программу main(), которую вы используете для проверки. В противном случае все, что у нас есть, — это две функции, в которых нет логических ошибок (но есть другие проблемы).   -  person PaulMcKenzie    schedule 09.06.2014
comment
Кроме того: if (this->name) В этом нет необходимости. Нет необходимости проверять наличие nullptr или NULL при вызове delete[]. Кроме того, что, если я передам нулевой указатель на setName? Ваша программа будет иметь неопределенное поведение, так как strlen(0) является UB.   -  person PaulMcKenzie    schedule 09.06.2014
comment
Кроме того, что, если я передам нулевой указатель на setName? Именно в этом и заключалась моя проблема!   -  person chillpenguin    schedule 09.06.2014
comment
в порядке. Но что делать, если передан нулевой указатель? Вы можете проигнорировать это и позволить программе, возможно, завершить работу (что и делает std::string).   -  person PaulMcKenzie    schedule 09.06.2014
comment
Ради бога, пожалуйста, не говорите мне, что я не должен использовать cstrings! -- Я думаю, вам следует пойти в кабинет своего профессора и сказать ему/ей, что, если задание не состоит в реализации std::string, вы будете использовать std::string. Не забывайте постоянно поддерживать зрительный контакт.   -  person Shoe    schedule 09.06.2014
comment
@chillpenguin Ирония в том, что профессора, которые говорят, что не используют std::string, в основном говорят своим студентам создавать программы с ошибками. Причина, по которой я это говорю, заключается в том, что я еще не видел, чтобы кто-нибудь, называющий себя начинающим или студентом-программистом на C++, создал строковый класс без ошибок. Цель написания программы - убедиться, что она свободна от ошибок, а просьба использовать cstrings гарантирует, что ваша программа не свободна от ошибок (если только вы не наймете опытного человека на SO, который напишет ее для вас).   -  person PaulMcKenzie    schedule 09.06.2014
comment
@PaulMcKenzie Я знаю, но это не мое решение. Поговорите об этом с моим профессором. Я просто думаю, что это забавно, что я специально сказал, что знаю, что std::string лучше, но я должен использовать cstrings. Я специально сказал это, чтобы люди не пытались рассказывать мне все о том, как глупо использовать cstrings. Поверь мне, я уже знаю. Но я ничего не могу с этим поделать. Когда я пишу свои программы не для школы, я буду использовать std::string. Но моя домашняя работа требует cstrings.   -  person chillpenguin    schedule 09.06.2014


Ответы (1)


Если это строка, код прерывается:

this->name = new char[strlen(name) + 1];

тогда name должен быть нулевым указателем, поскольку ничто больше не разыменовывается. name разыменовывается внутри функции strlen. Просто напечатайте значение переменной в вашем отладчике, и вы будете уверены.


Кроме того, используя то же имя переменной в установщике, например:

struct A
{
    void set(int a){this->a = a;}
    int a;
};

не является хорошей практикой. Просто используйте:

struct A
{
    void set(int na){a = na;}
    int a;
};

or

struct A
{
    void set(int a){a_ = a;}
    int a_;
};
person Martin Drozdik    schedule 08.06.2014
comment
Вау, ты был прав. Похоже, мне нужно исправить новую ошибку, поскольку этого не должно было случиться... Я приму ваш ответ, как только stackoverflow позволит мне это сделать. - person chillpenguin; 09.06.2014
comment
@chillpenguin - Вы знаете, что передача указателя NULL на std::string является неопределенным поведением, другими словами, вы все равно могли потерпеть крах, даже если использовали std::string. Так что, возможно, вам не стоит исправлять свой класс Data. Что вам следует исправить, так это код, использующий класс Data. - person PaulMcKenzie; 09.06.2014
comment
+1 .. хорошая работа, ответив на вопрос, и сделав еще один шаг, предоставив OP несколько полезных альтернатив кода! - person ddavison; 09.06.2014
comment
Часть вашего ответа, которая не является хорошей практикой, встроена в мое домашнее задание, и я не могу ее изменить. Я могу изменить только файлы .cpp, но не файлы .h. В файле .h уже было объявление функции (с аргументами) и переменные-члены класса. Это мой инструктор использует одни и те же имена для переменных-членов и аргументов функций... - person chillpenguin; 09.06.2014