Warm tip: This article is reproduced from serverfault.com, please click

C++ read memory faild

发布于 2020-11-28 21:43:24

I have 2 classes:

class b_class
{
public:
    int time_viewed;
    int parent_course;

    b_class()=default;

    b_class(int parent_course):time_viewed(0), parent_course(parent_course){
    }
};

and:

class b_course
{
public:

    int course_id;
    int num_of_classes;
    b_class **classes;

    b_course(int course_id,int num_of_classes);
};

In the latter I wrote the following code:

b_course::b_course(int course_id,int num_of_classes) {
    this->course_id=course_id;
    this->num_of_classes=num_of_classes;
    classes=new b_class*[num_of_classes*sizeof(b_class*)];
    for (int i=0;i<num_of_classes;i++)
    {
        classes[i]->time_viewed=0;
        //classes[i]->parent_course=course_id;
    }
}

But I'm getting an error because I am trying to access some memory which shouldn't be accessed.

read memory from 0x7000000000000000 failed (0 of 4 bytes read)

anyone know what is the reason for this?

classes is an array of pointers to b_class

Questioner
john
Viewed
0
Remy Lebeau 2020-11-29 06:02:10

You are allocating an array of pointers that don’t point at any valid objects. And you are allocating more space for the array then you actually need.

b_course::b_course(int course_id,int num_of_classes) {
    this->course_id = course_id;
    this->num_of_classes = num_of_classes;
    classes = new b_class*[num_of_classes]; // <- get rid of sizeof() here
    for (int i = 0; i < num_of_classes; i++)
    {
        classes[i] = new b_class(/*course_id*/); // <- add this
        classes[i]->time_viewed = 0;
    }
}

That being said, a better option is to allocate an array of objects instead of an array of pointers, eg:

class b_course
{
public:

    int course_id;
    int num_of_classes;
    b_class *classes;

    b_course(int course_id, int num_of_classes);
};

b_course::b_course(int course_id, int num_of_classes) {
    this->course_id = course_id;
    this->num_of_classes = num_of_classes;
    classes = new b_class[num_of_classes];
    for (int i = 0; i < num_of_classes; i++)
    {
        classes[i].time_viewed = 0;
        //classes[i].parent_course = course_id;
    }
}

Either way, since you are allocating objects dynamically, be sure to follow the Rule of 3/5/0 by also implementing a destructor to free the objects and array, and a copy constructor and copy assignment operator to make copies of the array and objects from one b_course to another.

The best way to handle all of this is to use a std::vector instead of new[], and let the compile handle the details for you, eg:

#include <vector>

class b_course
{
public:

    int course_id;
    std::vector<b_class> classes;

    b_course(int course_id,int num_of_classes);
};

b_course::b_course(int course_id,int num_of_classes) {
    this->course_id=course_id;
    this->classes.resize(num_of_classes);
    for (int i=0;i<num_of_classes;i++)
    {
        classes[i].time_viewed=0;
        //classes[i].parent_course=course_id;
    }
}