记录一个奇怪的问题:代码中只要访问某对象的成员就会发生段错误,程序立即异常退出。

11月13日晚

问题情景

问题发生在编写rpc项目的时候,项目已经编写完成。在测试的时候发现了这个问题。问题代码如下:

// 创建 MprpcController 对象
MprpcController *controller = new MprpcController();

// 发起rpc方法调用
stub.Login(controller, &request, &response, nullptr);

if (controller->Failed())
{
	// 处理相应逻辑
}
else
{
	// 处理相应逻辑
}

问题出现在上面代码的第7行,只要访问controller的成员就发生段错误(这一点可以确定)。按道理来说这里不应该出现段错误,因为段错误一般是数组越界、访问了空指针或是访问了已经释放的内存。但是我使用gdb调试打印这里controller的值,并不是nullptr,那就只有可能是访问了已经释放的内存,又由于controller的值并不为nullptr,应该是原来存放controller指向对象的内存又放了别的东西。但是我不知道为什么会发生这样的情况,我觉得按照逻辑来说这是不可能的,原因如下:

  • 从创建controller起到第七行代码,中间只调用了一个成员函数,controller作为该函数的参数被传了进去,但是传进去的是指针,Login函数内部的形参指针,是controller的拷贝,即使在Login函数的作用域中销毁了该形参,仍然影响不到controller所指向的对象。

所以我不理解这里为什么会发生段错误。gdb调式时有个奇怪的现象,我尝试使用p controller->m_failed打印controller的成员对象,输出结果告诉我他没有名为m_failed的成员对象。这一切似乎都在证实上面的猜测。但是我不知道controller所指对象究竟是怎么被释放的。

错误解决办法

解决方法很简单,既然可能的错误原因是访问了已被释放的内存,那么我就让controller所指对象根本不可能被释放。就是使用new申请一片堆内存,最后用deletecontroller释放掉,只需做两行修改。代码如下:

// 创建 MprpcController 对象
MprpcController *controller = new MprpcController();

// 发起rpc方法调用
stub.Login(controller, &request, &response, nullptr);

if (controller->Failed())
{
    std::cout << controller->ErrorText() << std::endl;
    LOG_ERR("%s", controller->ErrorText().c_str());
}
else
{
    if (0 != response.result().errcode())
        std::cout << "Rpc login response error: " << response.result().errmsg() << std::endl;
    
    std::cout << "Rpc login success: " << response.success() << std::endl;
}
delete controller;

求路过的大佬解答一下我的问题

11月14日上午

我想明白了

昨天晚上脑子抽抽儿了,我忽视了一个基础而又关键的问题。

MprpcController *controller;

像这样的语句只能声明一个指针,内存里不论是堆还是栈都没有实际的MprpcController对象。还需要手动去创建一个对象,然后让controller指向它。

这么简单的错误以后别再犯了🙏🙏🙏🙏🙏🙏🙏

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值