是否检查nullptr 100%是否在内存布局方面避免段错误?

问题描述 投票:2回答:3

可以说我正在遍历一个数组,但是由于我的循环很愚蠢,所以超出了这个数组。如果内存中的对象直接位于与此数组相同类型的数组之后,则可以检查array[invalid_index] == nullptr保护我?

检查索引(未知大小)对于C数组是否有效的正确方法是什么?

c++ segmentation-fault nullptr memory-layout
3个回答
7
投票

无法通过指向数组第一个元素的指针来确定数组的大小。您需要以某种方式传达尺寸。

通用策略是将数组保留为数组,并通过类型系统传递大小,将大小作为单独的值提供,或使用前哨值(例如c字符串中的空字符)。在c ++中,建议使用始终知道其自身大小的std::vectorstd::array

试图取消引用超出该数组范围的数组元素是未定义的行为。尝试读取array[invalid_index]时,您将具有未定义的行为。因此,不可能将array[invalid_index]用于任何有用的目的,包括边界检查。 nullptr根本不起作用。


5
投票

否,检查nullptr不会保护您。完全没有0%。

是您创建了相关数组的。检查索引是否有效的正确方法是知道您创建的数组的大小(执行此操作;请记住:创建数组的是[[you),然后检查索引是否在范围内。更好的是,编写代码以使索引最初不会超出范围,因此,无需检查就可以开始...

除了在数组的最后一个元素之后的假设元素之外,仅尝试仅偶数[[compute(甚至不访问,只是计算)不属于数组的元素的地址的尝试立即调用未定义行为[expr.add]/4。而且,无一例外,无论如何,尝试访问实际上不是数组元素的元素总是会调用未定义的行为。 100%。内置的下标运算符只是用于计算给定元素的地址并访问该地址[expr.sub]/1上的对象的简写形式。因此,在输入未定义的行为域之前,您实际上甚至还没有达到

可以将读取的值与nullptr进行比较的地步…


0
投票
许多C API与使用它的程序员有某种约定,即他们将遵守API指定的约定,而无需对该约定进行任何严格的机械强制执行。例如,基于C的String API大多断言字符串总是以Null结尾,并且正确使用任何基于C的String API都将假定并依赖于以Null结尾的字符串。

签订此合同时,

通常被认为是安全的进行这类检查,因为传递给您字符串的人通常可以通过用专门为实现此合同而明确指定的额外null值,例如:

char string[13] = "Hello World!"; //string[12] contains the value 0 /*...*/ char const* str = string; do { char curr = *str++; if(curr == 0) break; /*...*/ } while(true); 在大多数基于C的String API中,在保证该合同的特定上下文内,该代码被视为“安全”。

但是这取决于程序员的行为,并且不能保证。对于程序员来说,对他们的代码和诸如此类的东西表现不佳并不需要太多:

char string[12] = "Hello World"; string[11] = '!';

将立即中断我刚刚显示的字符串循环。这就是为什么C ++程序员(正确地,我认为)认为这类检查是不安全的:除非您信任用户(程序员)遵守规则,否则无法保证它们绝对正确。

这就是为什么我们偏爱不会意外中断的API。 

std::string string = "Hello World!"; for(char curr : string) { //for-each loop, intrinsically safe unless the iterators are improperly implemented /*Do whatever with curr*/ }

因此,请回到您的原始问题:处理此问题的安全方法是使用专门设计的可确保我们安全的物品。使用std::array<T, N>代替T arr[N],这将允许使用for-each循环。如果您需要使用基于索引的迭代,则在性能不高的任何情况下,都建议使用at(index)而不是[index]。这些做法将使您的代码安全,而不仅仅是相信您的数据已正确配置。

© www.soinside.com 2019 - 2024. All rights reserved.