Как исправить «Место чтения нарушения доступа» в этом коде - PullRequest
1 голос
/ 28 марта 2019

запустите этот код, я получил сообщение об ошибке, похожее на это

'Исключение, выданное в 0x778D7FCB (ntdll.dll) в Project1.exe: 0xC0000005: Место чтения нарушения доступа 0x00000014.'

Эта ошибкапроисходит в этой строке

~UnivStudnet() {
delete[]major; // error
    }
#include <iostream>
#include <cstring>
using namespace std;

class Person {
private:
    char * name;
public:
    Person(const char * myname) {
        name = new char[strlen(myname) + 1];
        strcpy_s(name, strlen(name), myname);
    }
    ~Person() {
        delete[]name;
    }

    void WhatYourName() const {
        cout << "My name is " << name << endl;
    }
};

class UnivStudnet : public Person {
private:
    char * major;
public:
    UnivStudnet(const char * myname, const char * const mymajor) :Person(myname) {
        major = new char[strlen(mymajor) + 1];
        strcpy_s(major, strlen(major), mymajor);
    }
    ~UnivStudnet() {
        delete[]major;
    }

    void WhoAreYou() const {
        WhatYourName();
        cout << "My major is " << major << endl;
    }
};

int main(void) {

    UnivStudnet st1("kim", "Mathenatics");
    st1.WhoAreYou();
    UnivStudnet st2("hong", "Physiscs");
    st2.WhoAreYou();
    return 0;
}

Как мне исправить эту ошибку?

Ответы [ 3 ]

4 голосов
/ 28 марта 2019

В двух strcpy_s строках есть ошибки.

strcpy_s(name, strlen(name), myname);

должно быть

strcpy_s(name, strlen(myname)+1, myname);

и аналогично

strcpy_s(major, strlen(major), mymajor);

должно быть

strcpy_s(major, strlen(mymajor)+1, mymajor);

Вызов strlen для вновь распределенных массивов символов name и major, которые имеют неопределенные значения, вызывает неопределенное поведение, которое является причиной вашего сбоя.

1 голос
/ 28 марта 2019

Ваше использование strcpy_s подозрительно.

    major = new char[strlen(mymajor) + 1];
    strcpy_s(major, strlen(major), mymajor);

Вторым параметром strcpy_s является выделенный размер буфера, указанный первым параметром. (И я только сейчас понял - основываясь на другом ответе, что strlen(major) не определено, прежде чем копировать в него!

Вы выделяете буфер достаточно большим для размещения строки, но последующий вызов strcpy_s указывает, что major недостаточно велик для хранения всей строки, включая нулевой символ.

Лучше:

    size_t len = strlen(mymajor) + 1;
    major = new char[len];
    strcpy_s(major, len, mymajor);

Повторите вышеприведенный шаблон и для параметра name базового класса.

1 голос
/ 28 марта 2019

Вы могли бы пойти больше C ++ - путь:

Вам необходимо заявить:

virtual ~Person()

деструктор в базовом классе и затем:

class UnivStudnet : public Person {
private:
    std::string major;
public:
    UnivStudnet(const char * myname, const char * const mymajor) :Person(myname), major(mymajor) {
    }
    virtual ~UnivStudnet() {
    }
...

Таким образом, вы достигнете того, что вам нужно, и не будете думать о распределении / освобождении памяти. Не забудьте заголовок #include <string>.

Точно так же, как в Person классе.

...