【发布时间】:2013-09-05 02:59:27
【问题描述】:
我正在学习如何在 C 中使用指针和结构。当然,我试图故意破坏我的代码以进一步了解该语言的工作原理。下面是一些测试代码,可以按我的预期工作:
#include <stdio.h>
#include <stdlib.h>
struct pair {
int x;
int y;
};
typedef struct pair pair;
void p_struct( pair ); //prototype
int main( int argc, char** argv ) {
pair *s_pair;
int size, i;
printf( "Enter the number of pair to make: " );
scanf( "%d", &size );
getchar();
printf( "\n" );
s_pair = (pair*)malloc( size * sizeof(pair) );
for( i = 0; i < size; i++ ) {
s_pair[i].x = i;
s_pair[i].y = i;
p_struct( s_pair[i] );
}
getchar();
return (EXIT_SUCCESS);
}
void p_struct( pair s_pair ) {
printf( "\n%d %d\n", s_pair.x, s_pair.y );
}
如前所述,据我所知,这段代码是有效的。
然后我决定像这样修改部分代码:
for( i = 0; i < size + 3; i++ ) {
s_pair[i].x = i;
s_pair[i].y = i;
p_struct( s_pair[i] );
}
此修改没有产生我预期的 seg 错误错误。尽管我超出了使用 scanf 函数为变量 size 赋值时明确设置的缓冲区,但所有“对”都被打印出来了。
据我了解指针(如果我错了,请纠正我),当我调用malloc 函数用于我的类型对 s_pair 的指针。我所做的是,当我将 for 循环修改为条件 i 时,我超出了最后分配的内存地址。
如果我理解正确的话,我的指针是否超出了它的保留内存限制,并且恰好是清晰的,因为它的右侧和附近没有被其他数据占用?这是溢出缓冲区时的正常行为吗?
补充一点,当我使用 i 的 for 循环条件进行测试时,我确实收到了 seg 错误。问题是,它仍然打印输出。如,当 size = 10 根据我制作的 p_struct 函数在屏幕上打印时,它会在屏幕上打印“0 0”对“24 24”。程序只有在到达底部的 getchar() 之一后才会因段错误而崩溃。我的程序究竟如何将值分配给超出缓冲区的对,将它们打印在屏幕上,然后突然决定在到达 getchar() 时因段错误而崩溃? i 似乎没有问题(尽管它仍然是错误的)。
作为记录,我还使用常规指针数组测试了这种行为:
int size, i, *ptr;
scanf( "%d", &size );
ptr = (int*)malloc( size * sizeof(int) );
for( i = 0; i < size + 15; i++ )
ptr[i] = i;
这会产生与上面完全相同的结果。在 i 处,段错误似乎没有任何问题。
最后,我也用数组进行了测试:
int i, array[10];
for( i = 0; i < 25; i++ )
array[i] = i;
对于条件 i ,我得到一个段错误,没有失败。当我将其更改为 i 时,我没有收到任何段错误。
如果我没记错的话,指针数组和数组之间的唯一区别是分配给数组的内存位于堆栈而不是堆上(对此不确定)。考虑到这一点,并考虑到 i 当 array[10] 不会产生任何段错误的事实,为什么 i 是个问题?在 for 循环期间,数组不是位于堆栈顶部吗?当它不关心 60 个额外字节时,为什么它会关心 100 个额外字节?为什么该数组缓冲区的上限不是一直到为整个堆栈保留的任意内存块的末尾?
希望所有这些对于决定阅读一个稍微醉酒的人的漫谈的人来说都是有意义的。
【问题讨论】:
-
未定义的行为:当您执行未定义的事情时,您的代码不需要崩溃或段错误。当你做一些非常错误的事情时,应用程序会在某些平台上崩溃。不过,系统不需要捕捉你在做未定义的事情;这是C语言中最常见的隐藏错误来源。
标签: c arrays pointers struct segmentation-fault