免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 5412 | 回复: 22
打印 上一主题 下一主题

[C] 骚年,千万别偷懒啊! [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2014-12-03 02:07 |只看该作者 |倒序浏览
本帖最后由 大众推荐 于 2014-12-03 14:48 编辑

话说。。。。2年前开始写的一个服务器程序,一年前上线,跑了一整年,没有挂过,前段时间刚小得意了一下。。。

结果,3周前,悲剧了。。
在过去3周里,挂了8,9次!!!!!!

由于是跑在公网上正处于服务期的,加上很久没怎么看过那份代码。。。再加上自己近来比较忙,也懒。。。。。种种原因。。。。
反正断断续续的跟了3,4天,根本不知道是怎么回事。。。。。
而且自己记得最近没怎么改这份代码。。。

从3天前开始,实在是无法容忍了,于是乎gdb,strace什么的都用上了,虽然coredump大致定位了位置并提示是访问了非法内存,
但仔细看了该部分的代码还是没有找到具体的问题。。。。

可以肯定的是,出现问题的哪行代码是很久没改过了。。。
反复阅读了这部分代码,实在是没问题。。。而且这部分代码跑了1整年了,都没有CRASH过。。。

这不科学啊!!!!!

仔细回想,大概在1个多月前,曾经尝试优化一下HASH TABLE。。。。
于是,看了一下这部分代码,也对比了一下之前的版本。。。。还是没有发现代码有问题。。。。

不过aaaaa.c 有类似这样的一个地方:
struct A* a (void)
{
#if XXX
      return aa();
#else
      return bb();
#endif
}

其中,之前代码只有 aa(),其他函数也只是直接调用 aa();
而 bb()是为了测试某一样东西加而加的,
而为了这个测试,a()也是后来加的。

由于之前吃过一次亏,所以赶紧找aaaaa.h来看,果然是没有声明a(void)!!!!!

-----------------------------------------------------
背景交代完毕,

A.由于a()返回的是一个malloc()出来的内存指针。
B.我没有在头文件中声明函数的返回类型(一般不会出现这种不声明返回类型的情况,除非是。。。有时候太HIGH了,根本就不记得了。。,而自己又不是每次都会清空编译时候的WARNING)。
C.C返回的默认指针,是只有32BIT的。前面的32BIT会自动CUT掉。
D.跑的服务器是64BIT的。

于是乎,当某个时刻malloc()出来的内存地址,其前面的32BIT不全为0的时候,而系统已经CUT掉了前面的32BIT,那么剩下了的地址就肯定不是我们想要的。。。。
或者说,在linux(UBUNTU AMD 64)中,调用隐式声明的API,返回默认是一个32位的INT,而接收这个返回值的时候,会转换这个返回值为指针,并自动补齐高32BIT的值
(貌似是,如果返回值的最高位是1,则全部补0XFFFFFFFF,如果返回值的最高位为0,则全部补0)

所以,当返回的地址第31-63 BIT(不是第32BIT开始,而包括31)不全为0的时候,自动补齐得出的地址,就肯定不对。。。这个时候去访问,就挂了。。。

-----------------------------------------------------
告诫各位新人,以后写代码,千万不要偷懒。。。
1.不可不声明全局函数。特别地,当返回值是一个指针的时候,+你跑的是64位的系统的时候。。。。。
2.不可放过编译时候的任何一个warning.当然,-Wall是必须的。



论坛徽章:
324
射手座
日期:2013-08-23 12:04:38射手座
日期:2013-08-23 16:18:12未羊
日期:2013-08-30 14:33:15水瓶座
日期:2013-09-02 16:44:31摩羯座
日期:2013-09-25 09:33:52双子座
日期:2013-09-26 12:21:10金牛座
日期:2013-10-14 09:08:49申猴
日期:2013-10-16 13:09:43子鼠
日期:2013-10-17 23:23:19射手座
日期:2013-10-18 13:00:27金牛座
日期:2013-10-18 15:47:57午马
日期:2013-10-18 21:43:38
2 [报告]
发表于 2014-12-03 08:16 |只看该作者
不看警告,自作孽不可活

论坛徽章:
59
2015年亚洲杯之约旦
日期:2015-01-27 21:27:392015年亚洲杯之日本
日期:2015-02-06 22:09:41拜羊年徽章
日期:2015-03-03 16:15:432015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:50:282015元宵节徽章
日期:2015-03-06 15:50:392015年亚洲杯之阿联酋
日期:2015-03-19 17:39:302015年亚洲杯之中国
日期:2015-03-23 18:52:23巳蛇
日期:2014-12-14 22:44:03双子座
日期:2014-12-10 21:39:16处女座
日期:2014-12-02 08:03:17天蝎座
日期:2014-07-21 19:08:47
3 [报告]
发表于 2014-12-03 08:17 |只看该作者
B.我没有在头文件中声明函数的返回类型(一般不会出现这种不声明返回类型的情况,除非是。。。有时候太HIGH了,根本就不记得了。。,而自己又不是每次都会清空编译时候的WARNING)。
<< Warning 一定要当做错误处理
C.C返回的默认指针,是只有32BIT的。前面的32BIT会自动CUT掉。
<< 很神奇, 还有这种编译器(Intel 64Bit的话, 返回值应当在RAX中, 足够64位, 64位的话, void *返回32位只能说是编译器的Bug)

论坛徽章:
14
巨蟹座
日期:2013-11-19 14:09:4615-16赛季CBA联赛之青岛
日期:2016-07-05 12:36:0515-16赛季CBA联赛之广东
日期:2016-06-29 11:45:542015亚冠之全北现代
日期:2015-07-22 08:09:472015年辞旧岁徽章
日期:2015-03-03 16:54:15巨蟹座
日期:2014-12-29 08:22:29射手座
日期:2014-12-05 08:20:39狮子座
日期:2014-11-05 12:33:52寅虎
日期:2014-08-13 09:01:31巳蛇
日期:2014-06-16 16:29:52技术图书徽章
日期:2014-04-15 08:44:01天蝎座
日期:2014-03-11 13:06:45
4 [报告]
发表于 2014-12-03 08:45 |只看该作者
回复 3# folklore
我猜,他的意思是,对于C89,如果省略返回类型的声明,则返回类型默认为int类型。比如 main(),等同于 int main(...)。
而在他的平台上,int只有32bits,而指针有64bits。

求职 : 机器学习
论坛徽章:
79
2015年亚洲杯纪念徽章
日期:2015-05-06 19:18:572015七夕节徽章
日期:2015-08-21 11:06:172015亚冠之阿尔纳斯尔
日期:2015-09-07 09:30:232015亚冠之萨济拖拉机
日期:2015-10-21 08:26:3915-16赛季CBA联赛之浙江
日期:2015-12-30 09:59:1815-16赛季CBA联赛之浙江
日期:2016-01-10 12:35:21技术图书徽章
日期:2016-01-15 11:07:2015-16赛季CBA联赛之新疆
日期:2016-02-24 13:46:0215-16赛季CBA联赛之吉林
日期:2016-06-26 01:07:172015-2016NBA季后赛纪念章
日期:2016-06-28 17:44:45黑曼巴
日期:2016-06-28 17:44:4515-16赛季CBA联赛之浙江
日期:2017-07-18 13:41:54
5 [报告]
发表于 2014-12-03 08:48 |只看该作者
公司一般会要求消除所有的编译器告警信息,这个是编码规范啊。
可是我也几乎从不消除编译器告警。

论坛徽章:
0
6 [报告]
发表于 2014-12-03 09:49 |只看该作者
C.C返回的默认指针,是只有32BIT的。前面的32BIT会自动CUT掉。
<< 很神奇, 还有这种编译器(Intel 64Bit的话, 返回值应当在RAX中, 足够64位, 64位的话, void *返回32位只能说是编译器的Bug)


>>严格来说,应该是 接受到的,比如说 char* p = aa();
我们看到的p 的值还是64BIT的,但是只有低位的32BIT是对的,高位的32BIT是错的。

个人理解,没有深入探究。

回复 3# folklore


   

论坛徽章:
0
7 [报告]
发表于 2014-12-03 09:51 |只看该作者
恩,对。。。

回复 4# bruceteen


   

论坛徽章:
0
8 [报告]
发表于 2014-12-03 09:55 |只看该作者

有时候,午夜,四周很安静,
喝了2口白酒或者其它。。。
在实现一个新功能什么的。。。。

反正,就是大脑很HIGH的时候。。。。
只管看结果。。根本就不会去看WARNING。。。。
一般而言,我会在2-4周左右集中clean up一下。。。。
。。。。嗯,反正这个不是好习惯。。

hellioncu 发表于 2014-12-03 08:16
不看警告,自作孽不可活

论坛徽章:
0
9 [报告]
发表于 2014-12-03 10:14 |只看该作者
骚年,这不是好习惯啊。。。。得改。。。

回复 5# zsszss0000


   

论坛徽章:
0
10 [报告]
发表于 2014-12-03 10:33 |只看该作者
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP