代码查错:map变量存储内容被破坏

场景描述:

linux通讯服务器工作时,接收第一个客户端消息能正常接收并处理完成;接收第二个客户端消息时就崩溃

1. 发现问题:
进程崩溃一般会产生core文件;
查看coredump文件:gdb gameserver /corefile/core-xxx;

[coredump文件使用的相关命令:
	ulimit -a 查看coredump文件是否允许创建 若结果为0,则表示关闭了此功能,不会生成core文件。
	ulimit -c unlimited   对创建coredump文件数量不限制
	cat /proc/sys/kernel/core_pattern 查看core文件保存位置
]
报错是试图访问一个内容被破坏的map:

std::map with 2 elements<error reading variable: Cannot access memory at address 0x204c42545f524569>

2.查找出错代码:
这个msgMap的定义是:
在这里插入图片描述
调用是:
在这里插入图片描述
现在知道是msgMap被破坏,但是不知道为什么被破坏,我们只知道第一次处理消息后被破坏。
所以进行单步调试,找到msgMap刚被破坏的那一行代码,我是执行一行,就打印一下 msgMap。
锁定了破坏msgMap的那行代码:
在这里插入图片描述
因为当我单步执行到 MYSQL_RES* res = xxx; 这行时【这一行刚到,还未真正执行】,发现msgMap已经被破坏了。

3.分析原因:
初看这只是一行很普通的拼接字符串的代码,但是由于SQL_CONF也是个map结构,所以我一开始的注意力就放在它上面了:
在这里插入图片描述
猜测1: 在map保存的函数指针调用内再使用其他map会破坏原map结构。
然后我写了个测试程序:

#include <iostream>
#include <map>

using std::map;
using std::cout;
using std::endl;

#define index_fun   2
#define index_value 2

typedef void (*_handler)(int);
void test_fun(int a);

static map<int,_handler> fun_map = {
	{index_fun  ,  &test_fun}
};

static map<int,int> value_map = {
	{index_value  ,  3}
};

int main()
{
	fun_map[2](4);
	fun_map[2](4);
	return 0;
}


void test_fun(int a)
{
	cout<<" test_fun begin "<<endl;
	cout<<" a = "<<a<<endl;
	cout<<" b = "<<value_map[2]<<endl;
	cout<<" test_fun end "<<endl;
}

测试结果:
在这里插入图片描述
发现并没有异常发生!!
那说明猜测1 不成立。

猜测2【逐行检查代码 发现的】:拼接后存放的char* sql;污染了msgMap的地址, 我没有给它提前分配内存,依赖sprintf的实现。
查看 sprintf 函数的官方说明,给定的存储buff一定要足够容纳拼接后的字符串,看来sprintf 里面是没有再做内存申请的。
在这里插入图片描述
4.解决问题:
出问题代码的上一句 char* sql;
修改为 char sql[100] = {0,}; 之后重新编译代码,程序不再崩溃!!

5.总结:
声明buff类指针的时候一定得思考下需不需要提前分配内存。

6.延伸思考和讨论:

  • char* sql 我没有分配内存的时候,它为何每次都是指向的 static msgMap的位置,至少是很接近,可以进一步了解下c++的内存模型,也可能依赖于操作系统,编译器的具体实现。
  • char* sql 的默认指向,是否是受到函数调用堆栈的影响呢。
  • const map不支持中括号操作符,原因是:中括号操作符在无法找到Key时,会插入新的Key,Value的pair,而const不允许此类操作。[更可怕的是 map插入默认值后,不删除 ,不仅占据空间,还污染数据。]
  • 或许我们使用 snprintf 更合适。
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tobybo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值