【问题标题】:Accessing an "out-of-bounds" index in an interpreted versus a compiled language在解释语言和编译语言中访问“越界”索引
【发布时间】:2015-09-14 03:54:10
【问题描述】:

在编译型编程语言(例如 C)和解释型语言(例如 MATLAB)中访问越界(负数或其他不可访问)索引有什么区别?

根据本网站的建议,我研究了许多有关访问越界索引的线程。然而,这些线程中的大多数只专注于解决源问题。也就是说,我已经能够从这个站点获得在使用 C 时访问越界索引会导致未定义的行为。通过使用 MATLAB 进行实验,我猜测解释性语言会执行测试以确定索引是否应该不可访问,并在访问越界索引之前“捕获”编写不佳的代码。这实际上是一般解释语言的情况,还是类似于 C(编译)语言,导致发生一定程度的未定义行为?在任何编译语言的程序中访问越界索引是否会导致未定义的行为?

【问题讨论】:

  • 这取决于语言。 Java 和 C# 已编译,但它们仍执行索引检查。它与编译/解释无关。
  • 啊,那么 MATLAB 实际上会检查越界索引吗?既然如此,我还假设没有访问由此产生的“越界”内存?
  • 许多语言检查越界访问并拒绝滥用内存(例如 Pascal)。它是一种编译语言。其他语言根本没有越界元素。如果您尝试访问不存在的元素,则会创建该元素(想想awk,Perl,...)。其他语言只是将其保留为未定义的行为(C、C++)。你得到你所得到的,这可能是也可能不是你应得或期望的——无论如何,它通常不是你想要的。
  • 我认为越界访问的处理只是语言本身固有的,而不是它的实现方式。我相信这会使我的问题无效,我很感激你的洞察力。谢谢你。然而,出于纯粹的兴趣,编译语言如何检查越界访问?这是在编译之前执行的吗?
  • 几乎总是在运行时完成。对于在编译时执行的边界检查等测试,您需要一个非常“丰富”的类型系统,例如依赖的类型。在没有自动边界检查的语言中,您通常可以自己实现它,或者使用各自的库函数,如 C++ vector,地址为:en.cppreference.com/w/cpp/container/vector/at

标签: c matlab interpreted-language


【解决方案1】:

一些语言将其保留为实现“细节”,而另一些语言则明确指定预期的行为......但随着时间的推移,对于几种编程语言来说,这已经发生了变化。

关于 C,在数组中使用负索引是完全合法(且有用)的,即使有时这可能会导致崩溃或代码/数据损坏(有意或无意),因为 C 试图不限制您作为程序员。如果您知道 C 语言是如何实现的,那么对于错误寻址的基于堆栈或基于 malloc 的内存块将会发生什么并没有太大的不确定性。 C 编译器可能会在编译期间发出警告以帮助防止错误(无意的负数组索引)。

其他语言为程序员决定并尝试阻止这些操作,无论是在编译时(PASCAL 是一个很好的旧示例)还是在执行时(JIT、VM 等)。除非语言规范定义了特定的行为,否则没有通用规则。

即使在 C 语言中,您也可以使用许多方法来防止意外损坏,例如 guardian memory areas 包围数组的内存块。然后可以由信号处理程序处理故障。

由于大多数其他语言依赖于 C/C++ 实现,这也是“更现代”的编程语言如何处理这些问题(负数组索引)作为规范或实现的一部分。也可以使用对负数组索引的测试,但会降低性能。

C# 或 Java 变量比 C 中占用更多空间,因为它们分配了更多信息(锁、垃圾收集、监护区域等),而 C 变量浪费的空间可能仅是在未替换默认行为时对齐导致的通过程序员更复杂的东西。

【讨论】:

    猜你喜欢
    • 2011-03-16
    • 2021-01-15
    • 2016-11-24
    • 2011-02-09
    • 1970-01-01
    • 1970-01-01
    • 2010-09-06
    • 1970-01-01
    • 2013-03-23
    相关资源
    最近更新 更多