在C中,是否可能总是在数组大小的1处生成SEGFULT?
假设您分配一些数组arr大小n,如下所示:在C中,是否可能总是在数组大小的1处生成SEGFULT?,c,arrays,segmentation-fault,C,Arrays,Segmentation Fault,假设您分配一些数组arr大小n,如下所示: int arr[n]; // Allocated fine printf("%d", arr[n]); // Segfault if possible 是否存在这样一个数字n,我可以始终触发printf行上的segfault?这可能是特定于某些操作系统的 我知道它的未定义行为,我知道当访问它并将其更改为超出范围时,将影响另一个内存区域,这将(可能)在以后给我带来重大问题 我的教授说,它不会总是segfault,我很好奇,在某些情况下,是否有任何方法可
int arr[n]; // Allocated fine
printf("%d", arr[n]); // Segfault if possible
是否存在这样一个数字n,我可以始终触发printf行上的segfault?这可能是特定于某些操作系统的
我知道它的未定义行为,我知道当访问它并将其更改为超出范围时,将影响另一个内存区域,这将(可能)在以后给我带来重大问题
我的教授说,它不会总是segfault,我很好奇,在某些情况下,是否有任何方法可以创建一个大小一定的数组,使用某种类型的操作系统或计算机,每次都能可靠地segfault
这可能吗?我是否可以创建一些条件,导致单个越界访问始终触发segfault
从理论上讲,这是否可能永远是真的?但实际上不会一直发生吗?不会。越界访问是未定义的行为。UB意味着任何事情都可能发生。在标准系统上,您通常可以找到一种持续导致SEGFULT的方法,但这并不能保证。如果您更改代码中的其他内容,可能会得到二进制移位,从而更改堆栈分配和程序结果 例如,在运行RTEMS 4.9.2的PowerPC 5200(不是很好的MMU)上,以下代码不会创建segfault:
int arr[5];
arr[6] = 10;
int *p = 0;
while (true)
*(p--) = 666;
事实上,即使这样也不会产生SEGFULT:
int arr[5];
arr[6] = 10;
int *p = 0;
while (true)
*(p--) = 666;
实际上,未定义的意思是未定义的
要在打印语句中执行此操作,您可以执行以下操作
printf("%d", arr[n]) // Out of bounds access
printf("%f", arr[n]) // wrong type access
但我将再次重申,虽然在特定情况下,这可能会重复出现故障,但决不能保证总是以这种方式发生
要用SIGSEGV可靠地停止POSIX系统,最好的办法是自己提高:
raise(SIGSEGV);
有关强制SIGSEGV信号的更多信息,请参见:
在这里:
否。越界访问是未定义的行为。UB意味着任何事情都可能发生。在标准系统上,您通常可以找到一种持续导致SEGFULT的方法,但这并不能保证。如果您更改代码中的其他内容,可能会得到二进制移位,从而更改堆栈分配和程序结果 例如,在运行RTEMS 4.9.2的PowerPC 5200(不是很好的MMU)上,以下代码不会创建segfault:
int arr[5];
arr[6] = 10;
int *p = 0;
while (true)
*(p--) = 666;
事实上,即使这样也不会产生SEGFULT:
int arr[5];
arr[6] = 10;
int *p = 0;
while (true)
*(p--) = 666;
实际上,未定义的意思是未定义的
要在打印语句中执行此操作,您可以执行以下操作
printf("%d", arr[n]) // Out of bounds access
printf("%f", arr[n]) // wrong type access
但我将再次重申,虽然在特定情况下,这可能会重复出现故障,但决不能保证总是以这种方式发生
要用SIGSEGV可靠地停止POSIX系统,最好的办法是自己提高:
raise(SIGSEGV);
有关强制SIGSEGV信号的更多信息,请参见:
在这里:
在一般情况下,正如本所指出的,这是未定义的行为。一般的答案是“永远不要依赖未定义的行为,它的影响永远不会是确定的” 然而,有两种可靠的方法可以在特定的、现代的、普通的系统上实现这一点,这些系统涵盖了现代PC机的大部分,但它不能在所有编译器、体系结构、操作系统等中移植
arr[-1]
,或将其与另一个极端对齐。不保证,但很可能,因为操作系统不允许您访问受保护的内存,或者如果您正在写入RODATA段,就是这样本指出,在一般情况下,这是一种未定义的行为。一般的答案是“永远不要依赖未定义的行为,它的影响永远不会是确定的” 然而,有两种可靠的方法可以在特定的、现代的、普通的系统上实现这一点,这些系统涵盖了现代PC机的大部分,但它不能在所有编译器、体系结构、操作系统等中移植
arr[-1]
,或将其与另一个极端对齐。不保证,但很可能,因为操作系统不允许您访问受保护的内存,或者如果您正在写入RODATA段,就是这样正如其他人所指出的,您无法确保在一般情况下出现分段错误,您可以尝试使用复杂的分配方法,使其在某些系统上更加系统化
有一种更好的方法可以调试代码并检测此类错误:有一种非常有效的工具可以用来调试代码:
valgrind
。检查它是否适用于您的环境。正如其他人所指出的那样,您无法确保在一般情况下出现分段错误,您可以尝试使用详细的分配方法,使其在某些系统上更系统化
有一种更好的方法可以调试代码并检测此类错误:有一种非常有效的工具可以用来调试代码:valgrind
。检查它是否适用于您的环境。注意:这使用了来自malloc
的数组,因此从技术上讲,它并不完全相同
但是,这将在末尾添加一个“保护”页面/区域,这通常会导致SEGFULT
我经常使用它来调试“逐个”数组索引。我发现它非常有用,我将它作为malloc
包装的一部分添加到了我的生产代码中
因此,如果目的是想出一些能够调试实际问题的方法,这可能会有所帮助: