如何在此代码中修复“访问冲突读取位置”

时间:2019-03-28 06:05:40

标签: c++ destructor

运行此代码,我遇到了这样的错误

'在Project1.exe中的0x778D7FCB(ntdll.dll)处引发了异常: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 个答案:

答案 0 :(得分:4)

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);

在新分配的具有不确定值的char数组strlenname上调用major会导致未定义的行为,这是导致崩溃的原因。

答案 1 :(得分:1)

您可以采用更多的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类中也可以这样做。

答案 2 :(得分:1)

您的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参数重复上述模式。