访问动态分配数组的越界元素/没有 SegFault

Posted

技术标签:

【中文标题】访问动态分配数组的越界元素/没有 SegFault【英文标题】:Accessing out-of-bounds elements of dynamically allocated arrays / w/o SegFault 【发布时间】:2011-12-10 17:34:12 【问题描述】:

我正在用 C 语言开发一个程序,它使用链表数组(原始哈希表)作为数据类型来表示某些日期信息。该数组有十二个元素对应一年中的月份,每个月都有一个包含数据节点的链表。

我开发了使用这种数据类型的模块,它运行良好。后来我发现我正在访问超出范围的数组元素(例如,通过索引 12 而不是 11 访问第 12 个元素)。但该程序始终如一地运行,没有发生任何事故。我从未收到分段错误。我已经更正了编码错误。谁能解释为什么访问越界元素不会导致段错误?

这不是第一次发生。我创建了一个动态分配的多维数组,为了测试,我尝试访问越界元素。该程序运行良好,产生了准确的结果,并且在大多数情况下都没有出现段错误。唯一一次我实现了,我不得不尝试访问大量越界的元素。

(这些程序目前是用于测试的 Windows 控制台应用程序。我正在使用 MinGW 进行编译。如果有帮助,我可以包含代码。)

【问题讨论】:

***.com/questions/671703/… 有一些关于这种 UB 的好帖子 【参考方案1】:

在 C 中,访问超出其边界的数组是未定义的行为

这意味着任何事情都可能发生,包括程序按您预期的方式运行。

C 语言不需要对数组访问进行边界检查,大多数 C 编译器也没有实现它。

例如,假设您声明:

int before;
int array[10];
int after;

这些在内存中的存储顺序是未定义的,但假设它们按照声明的顺序连续存储。如果您尝试访问array[-1],您可能会改为访问before。如果您尝试访问array[10],您可能会改为访问after

程序员有责任避免访问超出其界限的数组。 或者在您的数组之前和/或之后可能没有分配任何内容。

打个比方:“路牌上写着我只能在绿灯时过马路。我在红灯上过马路,什么也没发生。为什么没有车撞到我?” (有些语言会不遗余力地汽车撞到你。C 不是其中之一。)

【讨论】:

谢谢,这很有帮助。 免责声明:这个类比不是我最初的想法;我想我是从 comp.lang.c 上的 Eric Sosman 那里得到的。【参考方案2】:

谁能解释为什么访问越界元素不会 导致段错误?

这是未定义的行为,它不需要段错误。在 Linux 上,您可以在 Valgrind 下运行程序来捕获此类错误。

【讨论】:

【参考方案3】:

SegFaults 是操作系统的产物。当一个进程试图访问不属于它的内存并且不是 C 语言的一部分时,它们会被抛出。在 C 中,访问越界元素只是未定义的行为,这意味着它可能会失败,也可能不会。例如,如果内存分配器提供的内存块大于您为数组请求的内存块,则操作系统不会关心您是否超出范围,因为您将访问属于您的进程的内存.在这种情况下,您只会在程序中遇到错误。

【讨论】:

【参考方案4】:

通过索引超出数组范围来访问数据是未定义的行为。在大多数情况下(特别是动态分配的内存),由于各种原因,访问数组“附近”(不太远)的数据不会出现段错误。内存可能以圆形块分配,比您请求的更大,或者“malloc”实现可能会放置一些任意的簿记信息等。最终结果是该内存块被映射,但可能包含从垃圾到重要预订的数据保存信息。不要依赖这种行为。

【讨论】:

谢谢,这也很有帮助。

以上是关于访问动态分配数组的越界元素/没有 SegFault的主要内容,如果未能解决你的问题,请参考以下文章

C++ 关于内存泄露问题。内存泄露是指用new 分配的内存没有用delete释放,如果未释放会有啥后果?

c内存读写越界

小狼,你家BOSS喊你面试啦!!!

动态内存管理

动态内存分配

C语言之动态内存管理(动态内存分配+经典笔试题+柔性数组)[建议收藏]