GCC编译器段内存错误问题

就自己打码的经验来看,在linux的gcc编译器中使用指针的时候,常常会出现段内存(segmentation fault)错误问题,我在写课后习题的时候就出现了这么一个问题。题目是要求处理4维矩阵(也就是一个二维数组啦)。

这是在用gdb调试的时候,出现的结果。重点在第一行。

将一个4维矩阵(matrix)传入参数**p中,结果在函数首次用到*(*(p+i)+j)的时候就出错了,但编译可以通过,只不过出现warning。

但在VC6.0下直接报错。连warning都不给。

如果把**p改为(*p)[4],也就是把类型改为指向一维数组的指针的时候,程序就可以正常运行。

在VC6.0下也可以通过。

看了习题答案,发现答案的函数参数直接用指针

不过为什么用2维数组就出错了呢?

原因是2维数组,在表达式上可以解读成指向一维数组的指针,2维数组在内存上是连续的,而数组名在表达式上可以解读成一个常指针,指向2位数组的第一个元素。

说到底2位数组还是指针(解读成),而不是指针的指针。因此他可以传值给指针,但在传给指针的指针的是时候,传过去的仍然是初始元素的地址,即p是初始元素的地址,*p是初始元素的值,**p呢?什么也不是,其值是不可预测的,因此linux系统就给了个segmentation fault。

 

值得注意的还有,在很多C语言的书中都有这么一句,在很多情况下,数组名可以看成指针;这句话并不总是对的,乱搞的话会出现还是会有段内存错误问题。

首先,指针可以对其值进行操作,如p++,p--,p=array等等;但是数组不行,否则会报错。

另外,当指针指向一个字符串常量,数组是字符数组时,若分别对其所指的值(对本身不会)进行修改,指针会报错,数组不会。

图中strcpy对指针指向的字符串进行修改。

例如这样,会报错。字符数组就不用说了,当然可以通过。咱们经常这么干。

只修改一个也不行。仍然报错(segmentation fault)

所以,如果你要写一个字符串数组,并且要对它进行操作的话,写成*p[ n ],也就是数组指针,让每个指针指向一个字符串常量,以此达到节省内存的目的是不太合理的。

另外一个常见的段内存错误是没有给指针赋值就改变它的值。

经常,我们用一个指针来当中间变量的时候常常忘了给他初始化,

结果只能是意料之中。

另外如果用NULL来初始化呢?那更加不行了,上面讲到NULL是程序的禁区,修改了他,同样会出现段内存错误。

 

总结一下,出现段内存错误(segmentation fault(core dumped))有一下原因:

1、使用一个地址不明的指针;例如指针的值是一个int类型的变量;int *p;int a; p = a;

2、修改指向字符串常量的指针;char *p = “AC OCEAN”;*(p+1) = 'A';    

    这里应该注意:这样写是合法的: char *p1 = “I love you”,char *p2 = “I beat you”,p1 = p2;

3、修改指向null的指针的所指值。

4、修改没有初始化的指针的所指值。

 

另外:数组名不一定总是等价于指针;

        指向数组的指针不是指针的指针;

        使用指针数组来操作字符串常量有可能弄巧成拙;

 

最后,编译器是不会对数组越界做检测的。如果越界,在unix或linux下会报段内存错误,在其他操作系统下会破坏其他内存或直接不给通过编译。unix下出现段内存错误会生成core文件,方便用gdb来调试。但是我在unbuntu17.10下报核心转储的时候没有生成core文件/(ㄒoㄒ)/~~。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章