记录一次关于Segment Fault的愚蠢错误

背景

在公司项目里写了个类,里面简单的流程就是,先读取下本机名字和IP,然后创建一个线程,差不多就是下面代码里的样子

class A
{
public:
	void start()
	{
		// Get Hostname
		char tmp_hostname[256];
		gethostname(tmp_hostname, sizeof(tmp_hostname));
		hostname = tmp_hostname;
		
		// Get ip
		hostent *host = gethostbyname(hostname.c_str());
		ip = inet_ntoa(*(struct in_addr*)*host->h_addr_list);
	
		// 注意这句话
		pthread_create(pthread_create(reinterpret_cast<pthread_t *>(&thread_id), NULL, service_func, (void *)this);
	}

	void* server_func(void* args)
	{
		// service loop
		while (1)
		{}
		return NULL;
	}
private:
	int thread_id;
	string hostname;
	string ip;
};

然后这段代码出现了segment fault,打印堆栈发现是hostname出了问题,当时查了半天没查出来,因为是在项目里面,当时机子跑了别的任务,24核跑满了,编译起来特别慢,有些卡,就换了个机子把这段代码单独拿出来跑,结果怎么跑都没出现同样的问题,就很奇怪,诶,怎么同一段代码,放在别的机子上就好了呢。。。

最后没办法换了种写法,代码就好了,当时觉得是玄学。。。

发现问题

过了几天,在thread_id下面加了别的变量,写了点新东西,大概就是下面这个样子

class A
{
public:
	...
private:
	int thread_id;
	char peer_ip[20];
};

然后这次发现,每次打印peer_ip总是不对,但是只要在peer_ip下面随便再搞个变量去用,就没有问题,这次结合上次的问题,突然发现。。。上次段错误好像是因为有地方把string的东西给改掉了,这次是有地方把peer_ip给改掉了,唯一有可能改掉的地方就是用thread_id的地方,因为peer_ip我都是正常操作的。

查找thread_id修改的唯一的地方,就是pthread_create的地方,打印peer_ip的每个字节,发现peer_ip的前四个字节被改掉了。4+4就是8个字节。

问题所在

看下pthread_t是个unsigned long,然后突然反应过来,我项目运行的机器是装的64位的Debian,但是我的另一台没问题的机器是32位ubuntu,呃,突然发现问题觉得自己很蠢:

  • 32位下的unsigned long是4字节的,所以用int给pthread_t用没有任何问题
  • 64位下的unsigned long是8字节的,所以用int给pthread_t用少了4字节。。

以上导致了segment fault,我太蠢了,所以同一段代码,这台没问题,另一台有问题。

总结

传参数的时候,不,是所有涉及到类型不一致的时候,除非确定没问题,否则类型要对应,不能瞎强转。

写一篇博客记录这个愚蠢的问题,博君一笑~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值