【问题记录】裸指针和智能指针

问题描述

今天写项目时(在与elastisearch服务端的交互模块),遇到一个裸指针和智能指针指向同一块空间,导致段错误Segmentation fault,特此记录。

//error code
#include "es.hh"

int main()
{
    // 创建es客户端,与es建立连接
    try
    {
        elasticlient::Client* client = new elasticlient::Client({"http://localhost:9200/"});

        // 创建索引
        EsIndex es_index(client, "user", "_doc");
        es_index.append("nickname", "text", "ik_maxword", true);
        es_index.append("user_id", "keyword", "standard");
        es_index.append("phone", "keyword", "standard");
        es_index.append("description", "text", "standard", false);
        es_index.append("avatar_id", "keyword", "standard", false);

        es_index.create();

        // 插入文档数据
        EsUpdate ud1(client, "user", "_doc", 1);
        ud1.addProperty("user_id", "USER4b862aaa-2df8654a-7eb4bb65-11111111");
        ud1.addProperty("nickname", "昵称 1");
        ud1.addProperty("phone", "手机号 1");
        ud1.addProperty("description", "签名 1");
        ud1.addProperty("avatar_id", "头像 1");

        ud1.submit();
        
        EsUpdate ud2(client, "user", "_doc", 2);
        ud2.addProperty("user_id", "USER14eeeaa5-442771b9-0262e455-e4663d1d");
        ud2.addProperty("nickname", "昵称 2");
        ud2.addProperty("phone", "手机号 2");
        ud2.addProperty("description", "签名 2");
        ud2.addProperty("avatar_id", "头像 2");

        ud2.submit();
    }
    catch (std::exception &e)
    {
        std::cout << e.what() << std::endl;
    }

    
    return 0;
}

其中,EsIndexEsUpdate对象都以智能指针shared_ptr保存一份es客户端的副本,用于与es服务端交互。

class EsIndex
{
public:
	//....
private:
    std::shared_ptr<elasticlient::Client> _client;
    //...
};

class EsUpdate
{
public:
	//....
private:
    std::shared_ptr<elasticlient::Client> _client;
    //...
};

刚开始以裸指针传入EsIndexEsUpdate,用于其内部创建智能指针。程序运行后报段错误,使用gdb调试后,提示异常信息如下:
在这里插入图片描述

错误原因

在这里插入图片描述
出了try作用域后,三个拥有智能指针的对象销毁,智能指针释放,计数器减到0,空间释放,此时elasticlient::Client对象被销毁了。
根据gdb报错信息,可能是程序结束前,client要结束与es服务端的对话Session,但是此时无法找到client了,所以报了段错误。

改正

不要混用裸指针和智能指针来指向同一块内存。 如果你决定使用智能指针来管理内存,就应完全依赖它,而避免在代码中保留指向同一内存的裸指针。

#include "es.hh"

int main()
{
    // 创建es客户端,与es建立连接
    try
    {
        // elasticlient::Client* client = new elasticlient::Client({"http://localhost:9200/"});
        auto client = std::make_shared<elasticlient::Client>(std::initializer_list<std::string>{"http://localhost:9200/"});
        // 创建索引
        EsIndex es_index(client, "user", "_doc");
        es_index.append("nickname", "text", "ik_maxword", true);
        es_index.append("user_id", "keyword", "standard");
        es_index.append("phone", "keyword", "standard");
        es_index.append("description", "text", "standard", false);
        es_index.append("avatar_id", "keyword", "standard", false);

        es_index.create();

        // 插入文档数据
        EsUpdate ud1(client, "user", "_doc", 1);
        ud1.addProperty("user_id", "USER4b862aaa-2df8654a-7eb4bb65-11111111");
        ud1.addProperty("nickname", "昵称 1");
        ud1.addProperty("phone", "手机号 1");
        ud1.addProperty("description", "签名 1");
        ud1.addProperty("avatar_id", "头像 1");

        ud1.submit();
        
        EsUpdate ud2(client, "user", "_doc", 2);
        ud2.addProperty("user_id", "USER14eeeaa5-442771b9-0262e455-e4663d1d");
        ud2.addProperty("nickname", "昵称 2");
        ud2.addProperty("phone", "手机号 2");
        ud2.addProperty("description", "签名 2");
        ud2.addProperty("avatar_id", "头像 2");

        ud2.submit();

        // 搜索内容
        // std::string search_body = R"({
        // "query": {
        //     "match_all": {}
        //     }
        // })";
        // cpr::Response response = client.search("user", "_doc", search_body);

        // std::cout << "状态码: " << response.status_code << std::endl;
        // std::cout << "查找内容:" << response.text << std::endl;
    }
    catch (std::exception &e)
    {
        std::cout << e.what() << std::endl;
    }

    
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值