测试智能指针——使用 valgrind 运行以下示例给出: 我在 Ubuntu 22.04.1 上使用 g++ 11.3.0:
g++ -g -Wall -o tempa tempa.cvalgrind --leak-check=full --show-leak-kinds=all ./tempa
#include <string>
#include <vector>
#include <memory>
//================
class Jvert {
public:
Jvert( std::string stgaparm)
:
stga(stgaparm)
{}
void addSub(
std::shared_ptr<Jvert> jsrc)
{
// Add jsrc to jsubs
std::shared_ptr<Jvert> pthis( this);
jsrc->jparent = pthis;
jsubs.push_back( jsrc);
}
std::weak_ptr<Jvert> jparent;
std::vector<std::shared_ptr<Jvert>> jsubs;
std::string stga;
}; // end class Jvert
//==============
int main( int argc, char * argv[]) {
std::shared_ptr<Jvert> jva = std::make_shared<Jvert>("aaa");
std::shared_ptr<Jvert> jvb = std::make_shared<Jvert>("bbb");
jva->addSub( jvb);
}
//==================
您正在
this
的原始指针创建一个
addSub
:
std::shared_ptr<Jvert> pthis( this);
这是有问题的,因为当 jva
和 jvb
超出
main
的范围时,将调用它们的析构函数,这将尝试删除它们持有的原始指针。由于
this
用于创建
pthis
,多个
shared_ptr
对象将尝试删除相同的原始指针,导致无效的释放。
要解决此问题,您可以将类更改为继承自
std::enable_shared_from_this<Jvert>
并使用 shared_from_this()
获取当前对象的
shared_ptr
:
#include <string>
#include <vector>
#include <memory>
class Jvert : public std::enable_shared_from_this<Jvert> {
public:
Jvert(std::string stgaparm)
: stga(stgaparm)
{}
void addSub(std::shared_ptr<Jvert> jsrc) {
// Add jsrc to jsubs
jsrc->jparent = shared_from_this();
jsubs.push_back(jsrc);
}
std::weak_ptr<Jvert> jparent;
std::vector<std::shared_ptr<Jvert>> jsubs;
std::string stga;
}; // end class Jvert
int main(int argc, char *argv[]) {
std::shared_ptr<Jvert> jva = std::make_shared<Jvert>("aaa");
std::shared_ptr<Jvert> jvb = std::make_shared<Jvert>("bbb");
jva->addSub(jvb);
}
通过使用 std::enable_shared_from_this
,您可以确保 single shared_ptr
控制对象的所有权,防止出现无效释放和无效读取的问题。C++ 中的智能指针