Double delete of data doesn't crash

前端 未结 3 389
心在旅途
心在旅途 2021-01-19 23:57

I am trying to learn C++ and was writing programs to learn Copy Constructors and Operator overloading. I am surprised that the below program when Copy constructor is used do

相关标签:
3条回答
  • 2021-01-20 00:20

    The behavior of "Undefined behavior" is just undefined. That means, no one put effort into that cases because that cases should not happen. Even a working program can be "Undefined behavior".

    In your special case of an double delete, what happens, really depends on the implementation of the allocator. A usual implementation is to put released memory into a list and a next allocation will be satisfied with an element out of this list. If you double delete a chunk of memory, it will be added to the list twice. And then two allocation will be satisfied with the very same chunk of memory and thus two object will be created at the same memory location.

    BTW: You destructor is already broken, as it doesn't use the array delete.

    0 讨论(0)
  • 2021-01-20 00:26

    I wirte this piece of test code, hope it will help here, I think crush is related to platform a lot, it is not just by chance, since this piece of code crush in linux ,but works fine in codeblock IDE

    #include <iostream>
    #include <cstring>
    #include <stdio.h>
    using namespace std;
    
    class XHandler
    {
        public:
        XHandler()
        {
                data = new char[8];
                strcpy(data, "NoName");
                std::cout<< "default construcor is called" << std::endl;
        }
        XHandler (const char *str)
        {
                data = new char [strlen(str) + 1 ];
                strcpy (data, str);
                 std::cout<< "param construcor is called" << std::endl;
    
        }
        XHandler (const XHandler &xh)
        {
                data = xh.data;
                std::cout<< "copy construcor is called" << std::endl;
    
        }
        XHandler& operator = (const XHandler &xh)
        {
                data = xh.data;
                std::cout<< "operator construcor is called" << std::endl;
    
                return *this;
        }
        ~XHandler()
        {
            std::cout<< "destrucor is called" << std::endl;
            print_dir();
            if (data)
            {
                delete [] data;
                data = NULL;
                std::cout<< "delete data" << std::endl;
            }
    
    
    
        }
        void debug()
        {
                cout << data <<endl;
        }
        void print_dir()
        {
            printf("location: %p\n",data);
        }
        private:
        char *data;
    };
    
    int main()
    {
        XHandler wm("hello"), wb("there");
        wm.debug();
        wb.debug();
        wm.print_dir();
        wb.print_dir();
        XHandler wc (wm);
        wc.print_dir();
        wc.debug();
        XHandler wd;
        wd = wc;
        wd.debug();
    }
    

    it crush in linux gcc4.1.2 ,it outputs

    param construcor is called
    param construcor is called
    hello
    there
    location: 0x502010
    location: 0x502030
    copy construcor is called
    location: 0x502010
    hello
    default construcor is called
    operator construcor is called
    hello
    destrucor is called
    location: 0x502010
    delete data
    destrucor is called
    location: 0x502010
    *** glibc detected *** ./test: double free or corruption (fasttop): 0x0000000000502010 ***
    
    0 讨论(0)
  • 2021-01-20 00:40

    Your program has undefined behavior.

    Problems:

    data = new char (strlen(str) + 1 );
    

    This doesn't allocate strlen(str) + 1 characters. Instead, it allocates a single character and places the strlen(str) + 1 value within. When you perform a strcpy afterwards, you are corrupting the stack through buffer overflow (writing strlen(str) -1 chars past the allocated space). To allocate an array you should use square brackets:

    data = new char [strlen(str) + 1 ];
    

    Second, you should delete the data with delete[] data;. Otherwise, you get undefined behavior.

    Third, your strcpy code doesn't copy the NULL terminator of the string. You should add a null terminator:

    data[ strlen(str) ] = 0;
    

    after the strcpy lines; (see comments).

    Additionally, there is no requirement that an application would crash on double delete. Deleting the same memory twice is UB.

    0 讨论(0)
提交回复
热议问题