人人都写过的5个Bug!

1. 变量未初始化
#include 
#include
int main()
{
int i, j, k;
int numbers[5];
int *array;
puts("These variables are not initialized:");
printf(" i = %d\n", i);
printf(" j = %d\n", j);
printf(" k = %d\n", k);
puts("This array is not initialized:");
for (i = 0; i < 5; i++) {
printf(" numbers[%d] = %d\n", i, numbers[i]);
}
puts("malloc an array ...");
array = malloc(sizeof(int) * 5);
if (array) {
puts("This malloc'ed array is not initialized:");
for (i = 0; i < 5; i++) {
printf(" array[%d] = %d\n", i, array[i]);
}
free(array);
}
/* done */
puts("Ok");
return 0;
}
These variables are not initialized: 
i = 0
j = 0
k = 32766
This array is not initialized:
numbers[0] = 0
numbers[1] = 0
numbers[2] = 4199024
numbers[3] = 0
numbers[4] = 0
malloc an array ...
This malloc'ed array is not initialized:
array[0] = 0
array[1] = 0
array[2] = 0
array[3] = 0
array[4] = 0
Ok
i 和 j 的值刚好是 0,但 k 值为 32766。在 numbers 数组中,大多数元素也恰好是零,除了第三个(4199024)。These variables are not initialized: 
i = 0
j = 1074
k = 3120
This array is not initialized:
numbers[0] = 3106
numbers[1] = 1224
numbers[2] = 784
numbers[3] = 2926
numbers[4] = 1224
malloc an array ...
This malloc'ed array is not initialized:
array[0] = 3136
array[1] = 3136
array[2] = 14499
array[3] = -5886
array[4] = 219
Ok
2. 数组越界
#include 
#include
int main()
{
int i;
int numbers[5];
int *array;
/* test 1 */
puts("This array has five elements (0 to 4)");
/* initalize the array */
for (i = 0; i < 5; i++) {
numbers[i] = i;
}
/* oops, this goes beyond the array bounds: */
for (i = 0; i < 10; i++) {
printf(" numbers[%d] = %d\n", i, numbers[i]);
}
/* test 2 */
puts("malloc an array ...");
array = malloc(sizeof(int) * 5);
if (array) {
puts("This malloc'ed array also has five elements (0 to 4)");
/* initalize the array */
for (i = 0; i < 5; i++) {
array[i] = i;
}
/* oops, this goes beyond the array bounds: */
for (i = 0; i < 10; i++) {
printf(" array[%d] = %d\n", i, array[i]);
}
free(array);
}
/* done */
puts("Ok");
return 0;
}
This array has five elements (0 to 4) 
numbers[0] = 0
numbers[1] = 1
numbers[2] = 2
numbers[3] = 3
numbers[4] = 4
numbers[5] = 0
numbers[6] = 4198512
numbers[7] = 0
numbers[8] = 1326609712
numbers[9] = 32764
malloc an array ...
This malloc'ed array also has five elements (0 to 4)
array[0] = 0
array[1] = 1
array[2] = 2
array[3] = 3
array[4] = 4
array[5] = 0
array[6] = 133441
array[7] = 0
array[8] = 0
array[9] = 0
Ok
3. 字符串溢出
char 值,也可以将其视为数组。因此,你也需要避免超出字符串的范围。如果超出,则称为字符串溢出。gets 函数读取数据。gets 函数非常危险,因为它不知道接收它的字符串中可以存储多少数据,只会天真地从用户那里读取数据。#include 
#include
int main()
{
char name[10]; /* Such as "Beijing" */
int var1 = 1, var2 = 2;
/* show initial values */
printf("var1 = %d; var2 = %d\n", var1, var2);
/* this is bad .. please don't use gets */
puts("Where do you live?");
gets(name);
/* show ending values */
printf("<%s> is length %d\n", name, strlen(name));
printf("var1 = %d; var2 = %d\n", var1, var2);
/* done */
puts("Ok");
return 0;
}
var1 = 1; var2 = 2 
Where do you live?
Beijingis length 7 
var1 = 1; var2 = 2
Ok
Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch 是世界上名字最长的城市,这个字符串有 58 个字符,远远超出了 name 变量中可保留的 10 个字符。var1和var2 ,都有可能被波及:var1 = 1; var2 = 2 
Where do you live?
Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogochis length 58 
var1 = 2036821625; var2 = 2003266668
Ok
Segmentation fault (core dumped)
var1 和 var2 不再是它们的起始值 1 和 2 。getline 函数就是一个不错的选择,它将分配足够大的内存来存储用户输入,因此用户不会因输入太长字符串而意外溢出。4. 内存重复释放
malloc 函数为数组和字符串申请内存,系统将开辟一块内存并返回一个指向该内存起始地址的指针。内存使用完毕后,我们一定要记得使用 free 函数释放内存,然后系统将该内存标记为未使用。free 函数一次。如果你第二次调用 free 函数,将导致意外行为,而且可能会破坏你的程序。#include 
#include
int main()
{
int *array;
puts("malloc an array ...");
array = malloc(sizeof(int) * 5);
if (array) {
puts("malloc succeeded");
puts("Free the array...");
free(array);
}
puts("Free the array...");
free(array);
puts("Ok");
}
free 函数时出现 core dump 错误:malloc an array ... 
malloc succeeded
Free the array...
Free the array...
free(): double free detected in tcache 2
Aborted (core dumped)
free 函数呢?一个最简单的方法就是将 malloc 和 free 语句放在一个函数里。malloc 放在一个函数里,而将 free 放在另一个函数里,那么,在使用的过程中,如果逻辑设计不恰当,都有可能出现 free 被调用多次的情况。5. 使用无效的文件指针
config.dat 文件里,程序运行时,就可以调用这个文件,读取配置信息。fopen 函数打开文件,然后该函数返回指向文件的流指针。fopen 函数将返回 NULL 。在这种情况下,我们仍然对其进行操作,会发生什么情况?我们一起来看下:#include 
int main()
{
FILE *pfile;
int ch;
puts("Open the FILE.TXT file ...");
pfile = fopen("FILE.TXT", "r");
/* you should check if the file pointer is valid, but we skipped that */
puts("Now display the contents of FILE.TXT ...");
while ((ch = fgetc(pfile)) != EOF) {
printf("<%c>", ch);
}
fclose(pfile);
/* done */
puts("Ok");
return 0;
}
Open the FILE.TXT file ... 
Now display the contents of FILE.TXT ...
Segmentation fault (core dumped)
fopen 函数打开文件后,使用 if (pfile != NULL) 以确保指针是可以使用的。小结
评论
