简体   繁体   中英

Why is my new allocated pointer automatically deleted on program exit?

I have the following class which I save in a file in binary mode:

class lol
{
public:
    ~lol() {
        std::cout << "destucted" << std::endl;
        system("pause");
    }

    int age;
    std::string name;
};

Now in my main I have this:

int main()
{
    {
        lol kar;
        kar.age = 17;
        kar.name = "Blabla";

        ytxt("class").Write(std::string((char*)&kar, sizeof(kar))); //Saves the class in binary mode
    }

    lol * asd;

    {
        std::string stClass = ytxt("class").Read();//reads the file in binary
        asd = (lol*)new char[stClass.length()];//asd is now allocated with new
        memcpy_s(asd, stClass.length(), stClass.c_str(), stClass.length());//copy the content of the file into the class
    }

    std::cout << "Name: " << asd->name << std::endl;//output
    std::cout << "Age: " << asd->age << std::endl;

    asd->age = 79;
    std::cout << "Age: " << asd->age << std::endl;

    delete asd;//I cannot delete it as lol
    //delete (char*)asd;//works but lol destructor is not called
    system("pause");
}

The content of the asd pointer is being printed to the console, the pointer is deleted and the destructor is called. At the end the exception is thrown.

When I do not delete the asd pointer everything is working fine, but the destructor of the asd pointer is not called. I know that the pointer is allocated as new char and I have to delete it as a new char , but is there another way where the delete operation calls the destructor of lol ?

ytxt("class").Write(std::string((char*)&kar, sizeof(kar)));

This line does save a dump of bytes. But you cannot load that dump of bytes and expect it to be a proper instance of your class again. That is not how binary serialization works. This only works for POD types (and probably not by that exact line either). If you want to save your data and load it later, you will need a different method.

Every other problem in your program comes down to having byte garbage where correct data should be.

Even if you fix your destructor, this code has no chance of working: storing bytes of an object that contains pointers and then trying to restore that object into another memory is incorrect.

Your lol class has std::string , which stores a pointer to the actual bytes of the string. When you copy bytes of kar into a file, you store pointers from your running program, and you do not store the content of the string itself.

When you restore an instance of lol from a file, its pointer is pointing to a piece of memory that has been de-allocated by kar 's destructor. This is undefined behavior.

You need to change your approach to serializing the object. The approach that you currently have cannot be salvaged.

Note: Situations when you place a class into memory allocated as an array of bytes require placement new operator. See this Q&A for information on how to do clean-up after placement new.

由于您的lol类包含一个std :: string,这是一个复杂的对象,并且具有内部内存管理功能,因此当它实际上不是真实对象而是文件中的某些随机字节时,尝试删除它会导致内存损坏/崩溃。

Only some C++ structures can be written and read as raw bytes and work in reasonable ways. The kind that works that way is called "plain old data", or pod for short. (In C++11 they broke it down into finer grained concepts, but that is a detail.)

A struct or class (same thing other than default public vs private) containing nothing but pod, no virtual, no destructors, no constructors, and built-in types like int or pointers and arrays to same is plain old data.

Reading/writing those as a stream of bits at least does something half sensible.

If it contains pointers, the address of the thing pointed to won't survive past program restart, so avoid that.

std::string does not qualify, and neither does anything containing it.

To save/load from a file you should look at the serialization problem. There are many, many techniques, but none of them are free.

As easy one is to define a free save( put_here, X const& _ function for some output archive type put_here . Then create overloads for it for each type you want to support. Do the same for load . For composite types, just save/load each element.

Adding tags and the like for versioning is also useful in non-trivial code.

For sequence containers like string, you can save it as save(here, str.size()); for (auto&&c:str)save(here, c); save(here, str.size()); for (auto&&c:str)save(here, c);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM