用PTA做题,做yjfdbm,一查就吓一跳,发博客冷静下来。 () #^.^# ) 1076Wifi密码(15分)以下是微博上的照片。 “亲爱的同学们,因为大家有时需要使用wifi,而且怕家长学习落后,所以现在把wifi密码设置为以下数学问题的答案。 A-1; B-2; C-3; D-4; 学生们请自己回答,每两天更换一次。 谢谢您的协助! ~”——老师们也在努力促进学生的学习……本题要求学生按照试卷上的对应关系编写一个程序,将一系列主题的答案翻译成wifi的密码。 这里简单地假设每个选择题有四个选项,只有一个正确答案。
//我的代码# include stdio.h # definemax 101 # definesize 5int main () {int N=0; char str[MAX][SIZE]; scanf('%d ',n ); if(n100||n0 )返回0; for(intI=0; i 4 * N; I ) Scanf('%s ',str[i]; if(str[I][2]=='t ' ) if ) str[I][0]=='a ' ) putchar('1' ); elseif(str[I][0]=='b ' ) putchar('2); elseif(str[I][0]=='c ' ) putchar('3' ); elseif(str[I][0]=='d ' ) putchar('4); } }返回0; }
修改后的正确代码:将MAX放大了5倍。 yjfdbm认为,n最安静的美女达到100人,MAX不符合MAX=4*N的条件,因此# includestdio.h.h # definemax 501 # definesize 5int main () include stdio . scanf('%d ',n ); if(n100||n0 )返回0; for(intI=0; i 4 * N; I ) Scanf('%s ',str[i]; if(str[I][2]=='t ' ) if ) str[I][0]=='a ' ) putchar('1' ); elseif(str[I][0]=='b ' ) putchar('2); elseif(str[I][0]=='c ' ) putchar('3' ); elseif(str[I][0]=='d ' ) putchar('4); } }返回0; }
3358www.Sina.com/1一个程序发生越境访问时,cpu会受到适当的保护,因此会出现segmentation fault。 根据上述说明,3358www.Sina.com/可能不存在此内存空间、受系统保护或存在
3358www.Sina.com/以下是典型的yjfdbm的理由。非关联空指针——这是一种特殊情况。 尝试访问内存管理硬件不存在的内存地址时,尝试在进程地址空间中访问内存的程序包含只读存储器(如代码段) http://www .
#includestdio.hintmain(void ) {int*ptr=NULL; *ptr=0; 返回0; }目前,在一、什么是yjfdbm?中,读取时可能会从野针产生随机数据,但没有yjfdbm;读取时从悬空指针产生有效数据,随机数据可能会被复盖。
3358 www.Sina.com/# include stdio.hint main (void ) int*ptr=) int* ) 0; *ptr=100; 返回0; } yjfdbm应该就是访问了不可访问的内存只读存储器提出了segmentation fault。 这可能发生在操作系统加载到只读存储器中的部分代码段或只读数据段中。
#包含
<stdio.h> #include <string.h> int main (void) { char *ptr = "test"; strcpy (ptr, "TEST"); return 0; } #include <stdio.h> int main (void) { char *ptr = "hello"; *ptr = 'H'; return 0; } 输出结果: yjfdbm(核心已转储)上述例子ANSI C代码通常会导致yjfdbm和内存保护平台。它试图修改一个字符串文字,这是根据ANSI C标准未定义的行为。大多数编译器在编译时不会抓,而是编译这个可执行代码,将崩溃。
包含这个代码被编译程序时,字符串“hello”位于rodata部分程序的可执行文件的只读部分数据段。当加载时,操作系统与其他字符串和地方常数只读段的内存中的数据。当执行时,一个变量 ptr 设置为指向字符串的位置,并试图编写一个H字符通过变量进入内存,导致yjfdbm。编译程序的编译器不检查作业的只读的位置在编译时,和运行类unix操作系统产生以下运行时发生 segmentation fault。
可以纠正这个代码使用一个数组而不是一个字符指针,这个栈上分配内存并初始化字符串的值:
#include <stdio.h> int main (void) { char ptr[] = "hello"; ptr[0] = 'H'; return 0; }即使不能修改字符串(相反,这在C标准未定义行为),在C char *类型,所以没有隐式转换原始代码,在c++的 const char *类型,因此有一个隐式转换,所以编译器通常会抓住这个特定的错误。
4、空指针废弃因为是一个很常见的程序错误空指针废弃(读或写在一个空指针,用于C的意思是“没有对象指针”作为一个错误指示器),大多数操作系统内存访问空指针的地址,这样它会导致yjfdbm。
#include <stdio.h> int main (void) { int *ptr = NULL; printf ("%dn", *ptr); return 0; }这个示例代码创建了一个空指针,然后试图访问它的值(读值)。在运行时在许多操作系统中,这样做会导致yjfdbm。
非关联化一个空指针,然后分配(写一个值到一个不存在的目标)也通常会导致yjfdbm。
#include <stdio.h> int main (void) { int *ptr = NULL; *ptr = 1; return 0; }下面的代码包含一个空指针,但当编译通常不会导致yjfdbm,值是未使用的。因此,废弃通常会被优化掉,死代码消除。
#include <stdio.h> int main (void) { int *ptr = NULL; *ptr; return 0; }还有,比如malloc 动态分配内存,释放、置空完成后,不可再使用该指针。
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char* str=(char* )malloc(100); if(*str) { return; } strcpy(str,"hello"); printf("%sn",str); free(str); str=NULL; strcpy(str,"abcdef"); return 0; } 输出结果: hello yjfdbm (核心已转储) 5、堆栈溢出 #include <stdio.h> #include <string.h> int main (void) { main (); return 0; } 输出结果: yjfdbm(核心已转储)上述例子的无限递归,导致的堆栈溢出会导致yjfdbm,但无线递归未必导致堆栈溢出,优化执行的编译器和代码的确切结构。在这种情况下,遥不可及的代码(返回语句)行为是未定义的。因此,编译器可以消除它,使用尾部调用优化,可能导致没有堆栈使用。其他优化可能包括将递归转换成迭代,给出例子的结构功能永远会导致程序运行,虽然可能不是其他堆栈溢出。
6、内存越界(数组越界,变量类型不一致等) #include <stdio.h> int main (void) { char test[10]; printf ("%cn", test[100000]); return 0; } 输出结果: yjfdbm(核心已转储) 三、一些注意事项 出现yjfdbm时,首先应该想到yjfdbm的定义,从它出发考虑引发错误的原因。在使用指针时,定义了指针后记得初始化指针,在使用的时候记得判断是否为 NULL在使用数组时,注意数组是否被初始化,数组下标是否越界,数组元素是否存在等在访问变量,注意变量所占地址空间是否已经被程序释放掉在处理变量时,注意变量的格式控制是否合理等参看:C语言再学习 -- GCC编译过程
1.yjfdbm的定义
Ansers.com
http://www.answers.com
Definition of "Segmentation fault"
http://www.faqs.org/qa/qa-673.html
2.《什么是yjfdbm》
http://www.linux999.org/html_sql/3/132559.htm
3.《Segment fault 之永远的痛》
http://www.linuxforum.net/forum/gshowflat.php?Cat=&Board=program&Number=193239&page=2&view=collapsed&sb=5&o=all&fpart=
4.《yjfdbmbug的调试》
http://www.cublog.cn/u/5251/showart.php?id=173718