为什么最后一个SR5对象不用重载的新操作员占据内存



当我运行此程序时,创建了sr1sr2sr3sr4对象,并将值分配给相应的变量。但是在sr5对象中,name保持空白,而roll_no百分比显示正确的值。

更改

的值
int MAX = 5;

to

int MAX = 6;

一切正常。

这是我的代码:

const int MAX = 5;
const int FREE = 0;
const int OCCUPIED = 1;
int flag = 0;
using namespace std;
void warning()
{
    cout<<"n------All memory occupied------"<<endl;
    exit(1);
}
class student_rec
{
    private:
        char name[25];
        int roll_no;
        float percentage;
    public:
        student_rec(char *n, int r, float per)
       {
            strcpy(name, n);
            roll_no = r;
            percentage = per;
       }
       student_rec()
       {
       }
       void set_rec(char *n, int r, float per)
       {
            strcpy(name, n);
            roll_no = r;
            percentage = per;
       }
       void show_rec()
       {
            cout<<"n-------------------n";
            cout<<"Name= "<<name<<endl;
            cout<<"Roll number= "<<roll_no<<endl;
            cout<<"Percentage= "<<percentage<<endl;
       }
       void *operator new (size_t sz);
       void operator delete (void *d);
};
struct memory_store
{
    student_rec obj;
    int status;
};
memory_store *m = NULL;
void *student_rec::operator new (size_t sz)
{
    int i;
    if(flag == 0)
    {
        m = (memory_store *) malloc(sz * MAX);
        if(m == NULL)
            warning();
        for(i=0; i<MAX; i++)
            m[i].status = FREE;
        flag = 1;
        m[0].status = OCCUPIED;
        return &m[0].obj;
    }
    else
    {
        for(i=0; i<MAX; i++)
        {
            if(m[i].status == FREE)
            {
                m[i].status = OCCUPIED;
                return &m[i].obj;
            }
        }
        warning();
    }
}
void student_rec::operator delete (void *d)
{
    if(d == NULL)
        return;
    for(int i=0; i<MAX; i++)
    {
        if(d == &m[i].obj)
        {
            m[i].status = FREE;
            strcpy(m[i].obj.name, "");
            m[i].obj.roll_no = 0;
            m[i].obj.percentage = 0.0;
        }
    }
}
int main()
{
    student_rec *sr1, *sr2, *sr3, *sr4, *sr5, *sr6, *sr7;
    sr1 = new student_rec("sandeep", 21, 78);
    sr1->show_rec();
    sr2 = new student_rec("sachin", 21, 78);
    sr2->show_rec();
    sr3 = new student_rec("sapna", 21, 78);
    sr3->show_rec();
    sr4 = new student_rec("vipin", 21, 78);
    sr4->show_rec();
    sr5 = new student_rec("niraj", 21, 78);
    sr5->show_rec();
    sr6 = new student_rec; // error all memory occupied.
    return 0;
}

我在Linux机器上运行此代码。

这是可怕的代码。它完全不知道C 对象模型。忘记它,然后从一本好的介绍性书开始,该书解释了对象生命周期以及如何正确创建新对象。

更多关于问题的解释:缺陷1

问题在student_rec::operator new ()中。这线:

    m = (memory_store *) malloc(sz * MAX);

让您认为m指向memory_store对象的某些有效数组。不幸的是,C malloc()用于分配原始内存。因此,该内存中没有有效的对象。否则说,m指向的对象处于未知状态。

以后,线

       m[i].status = FREE;

处理m指向的对象,就好像它们已经有效一样。这是不确定的行为。如果您不为对象分配C 方式(例如new而不是malloc()),则首先需要使用新的位置来创建它们。

现在,对于您的简单对象琐碎对象,这不会造成太多损害。还有另一个缺陷。

甚至更多关于问题的解释:致命缺陷2

存在第二个严重问题:malloc仅分配sz * MAX字节。由于student_rec的操作员被超载,因此sz将被称为sizeof(student_rec)。但是您的代码假定是sizeof(memory_store),因此分配的内存至少sizeof(int)*n字节太短!

这就是为什么增加最大值(因此分配比5个对象所需的更多内存)似乎起作用的原因。

其他备注

像您一样使用全局变量,将m暴露于外界非常危险且容易发生。假设在其他一些功能中,您想使用局部变量m,但忘记声明它。您可以比预期的要快得多地破坏数据结构!您最好使其成为student_rec的私人静态成员。

忘记用于存储C字符串的固定字符阵列。如果一个名称比预期的要长,您会发现另一个很难发现的严重问题(在这种情况下,strcpy可能会导致内存损坏)。如果您在C 中进行编码,请利用string,以免担心这样的细节: - )

风格备注:为什么不使flag成为布尔值并使用true&amp;false而不是0和1?

风格说明:warning()功能具有误导性名称:warning()建议您发出警告并继续。为什么不给它一个自记录的名称,例如fatal_error()warning_and_exit()

最新更新