为什么最后一个sr5对象没有占用带有重载new运算符的内存?

时间:2017-09-16 17:15:49

标签: c++ memory-management operator-keyword new-operator

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

更改

的值时
int MAX = 5;

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机器上运行此代码。

1 个答案:

答案 0 :(得分:0)

这是可怕的代码。它完全没有意识到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()),则首先需要使用placement new创建对象。

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

关于出了什么问题的更多解释:致命缺陷2

还有第二个严重问题:malloc仅分配sz * MAX个字节。由于student_rec的运算符过载,将调用szsizeof(student_rec)的运算符。但是你的代码假设它是sizeof(memory_store),所以分配的内存至少sizeof(int)*n个字节太短!!

这就是为什么增加MAX(从而分配比5个对象所需的更多内存)似乎有效。

其他评论

像你一样使用全局变量,将m暴露给外界,是非常危险且容易出错的。假设在其他一些函数中你想使用局部变量m,但忘记声明它;你可能会比你期望的更快地破坏你的数据结构!您最好将其设为student_rec的私有静态成员。

忘记用于存储C字符串的固定字符数组。如果名称长于预期,则会出现另一个难以发现的严重问题(strcpy可能会导致内存损坏)。如果您使用C ++编写代码,请利用string以免担心此类细节: - )

文体评论:为什么不将flag作为布尔值并使用true&amp; false而不是0和1?

文体评论:warning()函数具有误导性名称:warning()表示您发出警告并继续。为什么不给它一个自我记录的名称,例如fatal_error()warning_and_exit()