Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
279 views
in Technique[技术] by (71.8m points)

c++ - why is std::string causing a memory leak in a class even after deleting

I am building a class that uses void* as a storage method. I am aware that it is not a good idea to use void*. But I don't know what value it will hold at compile time, so I thought it was the best solution. It works perfectly with everything, including C strings, but doesn't work with std::string. It causes a really bad memory leak. I've built a basic model of the class that has the same problem.

#include<iostream>
#include<string>

class CLASS {
public:
    void* data;

    CLASS(std::string str) {
        std::string* s = new std::string;
        *s = str;
        data = s;
    }

    ~CLASS() {
        delete data;
    }
};

int main() {
    std::string str = "hi";
        while (true)
        {
            CLASS val(str);
        }
}
question from:https://stackoverflow.com/questions/65947287/why-is-stdstring-causing-a-memory-leak-in-a-class-even-after-deleting

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

If you allocate a string, cast the pointer to a void *, then delete that, you will be trying to delete a void thing, not a string thing. For example, any class that allocates secondary storage (above and beyond the actual object being created with new) will most likely run into trouble:

#include <iostream>

class Y {
public:
    Y() { std::cout << "y constructor
"; }
    ~Y() { std::cout << "y destructor
"; }
};

class X {
public:
    X() { std::cout << "x constructor
";  y = new Y(); }
    ~X() { delete y; std::cout << "x destructor
"; }
private:
    Y *y;
};

int main() {
    X *x = new X();
    delete (void*)x;
}

This code will "work" in that it's legal but it will not do what you expect:

x constructor
y constructor

And a decent compiler should warn you about it:

program.cpp: In function ‘int main()’:
program.cpp:19:19: warning: deleting ‘void*’ is undefined [-Wdelete-incomplete]
   19 |     delete (void*)x;
      |                   ^

You should be deleting the type you allocated, to ensure the correct destructor is used. In other words, getting rid of the cast in the code shown above (so that you delete the correct type) will work out better:

x constructor
y constructor
y destructor
x destructor

Modern C++ has type-safe types which will do the heavy lifting for you, such as variant or any (if your single class needs to store a variety of types decided at run-time), or templates (if it can be used for one type but any of a variety). You should investigate those as an alternative to void *.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...