我正在用C开发一个程序,它使用一组链表(一个原始哈希表)作为数据类型来表示某些日期信息。该数组有12个元素,对应于一年中的月份,每个月都有一个包含数据节点的链表。
我开发了使用此数据类型的模块,它工作正常。我后来发现我正在访问超出界限的数组元素(例如,通过索引12而不是11来访问第12个元素)。但该计划始终如一地顺利进行。我从未收到过分段错误。我已经纠正了编码错误。任何人都可以解释为什么访问越界元素不会导致段错误吗?
这不是第一次发生。我创建了一个动态分配的多维数组,为了测试,我试图访问越界元素。该程序运行良好,产生了准确的结果,并且在大多数情况下没有出错。我唯一一次获得一个,我不得不尝试访问基本上越界的元素。
(这些程序目前是用于测试的Windows控制台应用程序。我正在使用MinGW编译。我可以包含代码,如果它有用的话。)
答案 0 :(得分:4)
在C中,访问其边界之外的数组是未定义的行为。
这意味着任何都可能发生,包括程序的行为与您预期的一样。
C语言不需要对数组访问进行边界检查,大多数C编译器都不实现它。
例如,假设您声明:
int before;
int array[10];
int after;
这些存储在内存中的顺序是未定义的,但假设它们按照它们声明的顺序连续存储。如果您尝试访问array[-1]
,则可以访问before
。如果您尝试访问array[10]
,则可以改为访问after
。
程序员的负担是避免访问超出其范围的数组。 或者在阵列之前和/或之后可能没有任何分配。
一个类比:“标志说我只允许在光线为绿色的时候过马路。我穿过红色,什么都没发生。为什么车没撞到我?” (有些语言不会让使汽车撞到你.C不是其中之一。)
答案 1 :(得分:1)
有人可以解释为什么访问越界元素不会 导致段错?
这是Undefined Behavior,它没有segfault。在Linux上,您可以在Valgrind下运行程序来捕获此类错误。
答案 2 :(得分:1)
SegFaults是OS生物。当进程试图访问不属于它的内存并且不是C语言的一部分时,它们被抛出。在C中,访问out of bounds元素只是未定义的行为,这意味着它可能会失败,而它可能不会。例如,如果内存分配器提供的内存块大于您对阵列的要求,则操作系统不会关心您是否超出范围,因为您将访问属于您的进程的内存。在这种情况下,您只是在程序中遇到错误。
答案 3 :(得分:1)
通过索引超出数组的范围来访问数据是未定义的行为。在大多数情况下(特别是动态分配的内存),访问数据“靠近”(不太远离界限),阵列不会因各种原因而发生段错误。内存可以以圆形块分配,大于您请求的内容,或者“malloc”实现可能会放置一些任意的簿记信息等。最终结果是该内存块被映射,但可能包含从垃圾到重要预订的数据保持信息。不要依赖这种行为。