第2章 这不是Bug, 而是语言特性

2.1 这关语言何事
1961年,NASA(美国航空航天局)程序员测试用于Mercury飞行的,计算环绕地球轨道的Fortran子程序.
Do 10 I = 1,10 误写为 Do 10 I = 1.10

malloc(strlen(str)); 任何时候看到这样的语句都几乎可以断定是错误的.
malloc(strlen(str)+1); 才是正确的写法.(字符串结尾符号'\0')

一个'L'的NUL用于结束一个ACSII字符串
两个'L'的NULL用于表示什么都不指向(空指针)

2.2 多做之过
由于存在fall through, switch语句会带来麻烦.
C语言理念: 程序员应该知道直接正在干什么, 而且保证自己的所作所为是正确的.
在C语言中, const关键字并不真正表示常量.()
相邻的字符串常量将被自动合并成一个字符串.
char *arr[] = {
'red',
'green'
'blue'
}
自动合并字符串后,实际效果:
char *arr[] = {
'red',
'greenblue'
}
缺省可见:
function apple() { /*在任何地方均可见*/}
extern function pear() {/*在任何地方均可见*/}
static function turnip() {/*在这个文件之外不可见*/}
缺省可见是错误的, 应该缺省采用有限可见性.
2.3 误做之过
符号重载:
static
extern
void
*
&
=
==
<=
<<=
<
()

p = N * sizof * q;
sizeof操作符(不是函数)把*q作为操作数.
apple = sizeof(int) * p; ???
运算符优先级:
早起gets()中的Bug导致Internet蠕虫.
gets()函数并不检查缓冲区的空间(事实上也无法检查)
如果调用提供一个指向stack的指针,并且gets()函数读入的字符数量超过了缓冲区空间
gets()函数将多出的字符进行继续写入后续的stack中,覆盖原先stack上的内容.
finger防护进程包含如下代码:
main(argc, argv)
	char *argv[];
{
	char line[512];
	...
	gets(line);
	...
}
建议采用fgets彻底取代gets()
gets(line); 
//修改为:
if (fgets(line, sizeof(line), stdin) == NULL) exit(1);
2.4 少做之过
标准参数处理
把lint程序错误地从编译器中分离出来
编译器日期破坏:
char * localized_time(char* filename)
{
	struct tm *tm_ptr;
	struct stat stat_bloc;
	char buffer[120];
	
	stat(filename, &stat_block);


	tmp_ptr = locatime(&stat_block.st_mtime);


	strftime(buffer, sizeof(buffer), "%a %b %e %T %Y", tm_ptr);


	return buffer;
}


// 问题: 返回一个指向stack内存的指针, 在函数结束后堆栈内存自动释放.


// 解决方案:
// 1.返回一个指向字符串常量的指针
//   缺点: 只适用于简单字符串
char * func() { return "Only works for simple strings"; }


// 2.使用全局声明的数组
//   缺点: 变量全局可见, 可能被修改, 内容容易被覆盖, 闲置不用时浪费内存空间.
char * func() {
	...
	my_global_array[i] = 
	...
	return my_global_arry;
}


// 3.使用静态数组
//   缺点: 内容在下次调用时被覆盖.闲置不用时浪费内存空间.
char * func() {
	static char buffer[20];
	...
	return buffer;
}


// 4.显示分配内存
//   缺点: 调用者负责内存释放, 内存分配与释放位置比较乱, 容易造成内存泄露.
char * func() {
	char * s = malloc(120);
	...
	return s;
}


// 5.调用者申请内存
//   
void func(char *result, int size) {
	...
	strncpy(result, "That'd be in the data segment, Bob", size);
}


buffer = malloc(size);
func(buffer, size);
...
free(buffer);
2.5 轻松一下---有些特性确实就是Bug
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值