标签 C 下的文章

走马观花ANSI C标准-介绍

大部分的关于C的著作都提到ANSI C Standard,但我相信少有C程序员真正细致阅读过ANSI C标准(当然了对于作C编译器的程序员来说这个标准肯定是烂熟于胸了^_^),在这个系列的文章中我将和大家一起浏览一下ANSI C标准(C99,以下称标准),呵呵,当然也不能面面俱到,只是“走马观花”。

1. 什么是“标准”(这里指编程语言标准)
按照comp.lang.c的C FAQ的意思:“标准只是把现存的实践整理成文。编程语言标准可以看作语言使用者和编译器实现者之间的协议。协议的一部分是编译器实现者同意提供, 用户可以使用的功能。而其它部分则包括用户同意遵守, 编译器实现者认为会被最受的规则。只要双方都恪守自己的保证, 程序就可以正确运行。如果任何一方违背它的诺言, 则结果肯定失败。

2. ANSI C Standard到底讲了啥?
这就是标准中"Scope"一节所要讲述的问题。按照标准说明:标准详细说明了使用C语言书写的程序的形式,规范对这些程序的解释。包括:
– C程序的表示法;
– C语言的语法和约束;
– 解释C程序的语义规则;
– C程序输入和输出的表示;
– 一份标准的实现的限定和约束。

3、有关标准中所用术语的解释
在标准的第3章列出了标准中所用的一些难解的术语、定义和符号。我想这些术语用英文解释应该更为精确,建议在看标准前认认真真的看一遍这些术语。有些术语解释第的确确让我弄清了我以前的一些疑惑。

4、“走马观花ANSI C标准”将按照ANSI C标准的章节分为:
 – 环境
 – 语言
 – 库
仅是计划而已^_^。

C程序员之“痛”

内存问题是C程序员永久的话题,也是最能让C程序员心痛的话题。内存bug即隐秘,危害又大,而且往往当你解决了它之后,你会发现你的错误是多么的低级。以我为例,看下面的两个case:

CASE1

背景: 配置信息读取
Bug现象: 通过打印语句观察到,在配置读取中间时刻,某一指针突然被置为NULL,出core。
耗时: 6小时
问题所在及分析: 经过6小时的不懈努力,终于发现了这一让我哭笑不得的低级错误。问题原因大致是这样的:
我定义了一个存储配置信息的结构体变量指针,并在初始化的时候给该指针在共享内存中分配空间,下面的代码就是我分配空间时的代码
xx_t *p;
…//

p = xx_malloc((void**)&p, sizeof(p));

正确的代码
p = xx_malloc((void**)&p, sizeof(xx_t));
我想我之所以花了那么长时间才找到这个问题,是被一些奇怪的现象所蒙蔽了,也是查找内存误操作问题经验不足所致。

CASE2

背景: Ftp客户端获取文件列表
Bug现象: 当Server端目录下文件个数很多时(如>=1000),以后的ftp操作全部失效,出现errno = 95、134等。
耗时: 7小时
问题所在及分析: 由于在文件少的时候,我们的ftp client工作一切正常,所以我们最开始怀疑的是接收数据缓冲区开得不够大。但是在加大缓冲区之后,问题依然存在。由于对FTP协议并不是很熟悉,导致在一些细节上又耽误了很多时间。之后我们看到一个奇怪的现象就是errno 95的出现,说明我们的ctrl channel socket已无效。我们使用最传统的调试方法使用打印语句,从创建Ctrl Socket开始,一直追踪到问题发生区域,并锁定一块区域的代码,在该代码之前ctrl socket为31, 之后ctrl socket居然变为1, 而且这段代码中并没有操作socket的语句。我们分析有两个可能:
1)这段代码运行时间过长,导致Ftp server关闭link;
2)该段代码有内存误操作,导致内存被污染;

我们使用排除法,首先注掉那段代码,取而待之的是sleep(30),我们想如果sleep 30秒,Ftp server不关闭link的话,那么就是第2种可能了,结果是的确有“内存误操作”,静态检查代码后,锁定在一个给指针数组赋值的语句上,察看上层代码后,发现这就是问题所在。用代码说明问题大致是这样的:
char *flist[200];

…//

int cnt = 0;
while (读取数据不为空) {
 p = malloc(…);
 …//
 flist[cnt] = p;
 cnt++; 
}

显然如果数据超过200条,数组必然越界。

总结:经过两个Case中,发现自己在找“内存误操作”问题上的经验不足,但同时经过这两个case,我总结一下几条,可能对以后的bug查找有所帮助。
a) 虽然“内存bug”不易查找和修改,但是一定要摆正心态,首先确定是“内存误操作”带来的bug;
b) “内存bug”绝大多数是极其低级的错误,所以首先要仔仔细细静态检查代码,可以按下面的顺序检查
 .搜索所有的malloc, memset, memcpy一类的内存操作函数,察看是否有“马虎”错误;
 .察看所有的数组变量,看是否有越界嫌疑
c) 打印语句是最简单,但是却是最有效的debug方法(我是这么认为的^_^),要利用好哟。

[注]:errno 95 — Socket operation on non-socket

如发现本站页面被黑,比如:挂载广告、挖矿等恶意代码,请朋友们及时联系我。十分感谢! Go语言第一课 Go语言精进之路1 Go语言精进之路2 Go语言编程指南
商务合作请联系bigwhite.cn AT aliyun.com

欢迎使用邮件订阅我的博客

输入邮箱订阅本站,只要有新文章发布,就会第一时间发送邮件通知你哦!

这里是 Tony Bai的个人Blog,欢迎访问、订阅和留言! 订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠 ,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您希望通过微信捐赠,请用微信客户端扫描下方赞赏码:

如果您希望通过比特币或以太币捐赠,可以扫描下方二维码:

比特币:

以太币:

如果您喜欢通过微信浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:
本站Powered by Digital Ocean VPS。
选择Digital Ocean VPS主机,即可获得10美元现金充值,可 免费使用两个月哟! 著名主机提供商Linode 10$优惠码:linode10,在 这里注册即可免费获 得。阿里云推荐码: 1WFZ0V立享9折!


View Tony Bai's profile on LinkedIn
DigitalOcean Referral Badge

文章

评论

  • 正在加载...

分类

标签

归档



View My Stats