360的evpp库的一处内存泄漏分析,shared_ptr的循环引用

本文分析了一个使用EvPP和EvNSQ库的C++程序中存在的内存泄漏问题。该程序通过HTTP查询nsqlookupd并连接到nsq,但因未能正确释放请求对象导致内存泄漏。文章详细解释了内存泄漏的原因,并提供了一个简单的示例来说明问题。

场景

使用evpp的evnsq的代码连接nsqlookupd进行Http查询,然后连接nsq,存在内存泄漏。

类似于这样的代码:

#include <evnsq/exp.h>
#include <evnsq/consumer.h>
#include <evpp/event_loop.h>


int OnMessage(const evnsq::Message* msg) {
    LOG_INFO << "Received a message, id=" << msg->id << " message=[" << msg->body.ToString() << "]";
    return 0;
}

int main(int argc, char* argv[]) {
    std::string nsqd_tcp_addr;
    std::string lookupd_http_url;
    nsqd_tcp_addr = "127.0.0.1:4150";
    lookupd_http_url = "http://127.0.0.1:4161/lookup?topic=test";

    if (argc == 2) {
        if (strncmp(argv[1], "http", 4) == 0) {
            lookupd_http_url = argv[1];
        } else {
            nsqd_tcp_addr = argv[1];
        }
    }

    evpp::EventLoop loop;
    evnsq::Consumer client(&loop, "test", "ch1", evnsq::Option());
    client.SetMessageCallback(&OnMessage);

    if (!lookupd_http_url.empty()) {
        client.ConnectToLoopupds(l
C++ 中,shared_ptr 常常被用来管理动态分配的资源。然而,当多个 shared_ptr 相互引用时,就会出现循环引用的问题,导致内存泄漏。为了解决这个问题,C++11 引入了 weak_ptr。 weak_ptrshared_ptr 的一种扩展,它可以指向一个由 shared_ptr 管理的对象,但并不拥有该对象的所有权。weak_ptr 可以被用来解决 shared_ptr 循环引用的问题。 当一个对象被多个 shared_ptr 共享时,每一个 shared_ptr 都会增加该对象的引用计数。如果其中一个 shared_ptr 被销毁时,该对象的引用计数会减少。但如果多个 shared_ptr 相互引用,就会导致循环引用的问题。例如: ```c++ class B; class A { public: std::shared_ptr<B> b_ptr; }; class B { public: std::shared_ptr<A> a_ptr; }; int main() { std::shared_ptr<A> a(new A); std::shared_ptr<B> b(new B); a->b_ptr = b; b->a_ptr = a; return 0; } ``` 在上面的代码中,A 和 B 互相引用,它们的引用计数永远不会为 0,导致内存泄漏。为了解决这个问题,我们可以将其中一个 shared_ptr 改为 weak_ptr。例如: ```c++ class B; class A { public: std::weak_ptr<B> b_ptr; }; class B { public: std::shared_ptr<A> a_ptr; }; int main() { std::shared_ptr<A> a(new A); std::shared_ptr<B> b(new B); a->b_ptr = b; b->a_ptr = a; return 0; } ``` 在这个例子中,A 持有一个指向 B 的 weak_ptr,而 B 持有一个指向 A 的 shared_ptr。这样,当 A 或 B 中的任意一个 shared_ptr 被销毁时,它们所指向的对象的引用计数都会减少,从而解决了循环引用的问题。 需要注意的是,当通过 weak_ptr 访问对象时,需要先将 weak_ptr 转换为 shared_ptr,否则无法访问对象。假设上面的例子中,我们需要访问 B 对象,可以这样做: ```c++ std::shared_ptr<B> b_ptr = a->b_ptr.lock(); if (b_ptr) { // 访问 B 对象的成员 } ``` 在上面的代码中,我们使用 lock() 方法将 weak_ptr 转换为 shared_ptr,如果转换成功,就可以访问 B 对象的成员了。 总之,weak_ptrshared_ptr 的一种扩展,可以用来解决 shared_ptr 循环引用的问题。通过将其中一个 shared_ptr 改为 weak_ptr,可以防止循环引用导致的内存泄漏
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值