【问题标题】:how to fix 'Access violation reading location' in this code如何修复此代码中的“访问冲突读取位置”
【发布时间】:2019-08-18 20:09:37
【问题描述】:

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

'在 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;
}

如何解决这个错误?

【问题讨论】:

  • @hsalimi 即使在这里一般情况下做得更好,这并不重要,因为没有从基类指针中删除
  • 也要实现复制/移动构造函数/赋值,否则如果进行复制操作,您将删除原始指针两次。
  • 您确定您给我们的代码会产生无效的访问权限吗?为什么不使用 std::string ?

标签: c++ destructor


【解决方案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 参数也重复上述模式。

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 我认为 OP 通过 documentation 声明第二个参数是目标字符串的大小。
    • 这里是strlen(myname) + 1,因为它刚刚在上面一行中更新了该尺寸。 strlen(name) 没有给出name 的分配长度。
    • 是的,你是对的。我只是想指出为什么 OP 可能会犯这个错误(除了不加 1)。顺便提一下答案。 :)
    【解决方案3】:

    您可以采用更多 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 &lt;string&gt;标头。

    Person 类中也是如此。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-31
      • 2016-05-28
      • 2017-01-09
      • 2014-11-09
      • 1970-01-01
      相关资源
      最近更新 更多