所以我有一个程序
#include "main.h"
#import <limits.h>
#import <stdint.h>
int foo(const void *src, void *dst, uint16_t len)
{
uint16_t index;
const uint8_t *srcRef = src;
uint8_t *dstRef = dst;
for(index = 0; index <= len; index++)
{
dstRef[index] = srcRef[index];
printf("-> %d - %d\n", index, srcRef[index]);
}
printf("%d\n", index);
return 0;
}
int main()
{
printf("max length of UInt16 is : %d\n", UINT16_MAX);
uint8_t arrOr[55];
uint8_t arr[55];
arrOr[54] = 7;
uint16_t len = 119;
foo(arrOr, arr, len);
return 0;
}
程序能够访问数组索引超出范围是否正常? (我实际上是期待它崩溃) 当数组长度为55时,它最多可以访问119(120次崩溃)。
当它56岁时,我仍然只能访问最多119次和120次崩溃
当它是57时,我最多可以访问135和136次崩溃。
我猜它试图访问整个程序的内存地址,而不仅仅是数组索引。但是当我将数组长度更改为57时,实际发生了什么,这让我可以通过将其增加到56来访问更多我无法访问的地址?
答案 0 :(得分:2)
看起来对齐很重要。
首先,这是undefined behavior所以不要依赖它。根据ISO C标准,访问越界是UB。
再次警告:以下任何内容都是高度依赖于实现的。由您自行决定。
好吧,先回答。你的猜测是正确的:
我猜它试图访问整个程序的内存地址,而不仅仅是数组索引。
有点有趣的是,你的数字120
和136
相差16,所以我猜它是由8的对齐引起的(你有2个数组)。在现代计算机中,内存中的数据与性能问题保持一致。对于典型的64位系统,它与8对齐,因此两个数组arr
和arrOr
都对齐到8个字节。也就是说,当你声明大小为57时,它实际上占用了64个字节的内存(所以如果你声明一个介于57和64之间的大小,你就不会观察到任何差异,但是你会在#&# 39; s 65)。
对于大于64的额外空间,可能是因为调用堆栈。这意味着您正在访问父函数中的变量,例如main
或WinMain
或上述任何内容。当您的程序启动时,系统会定义一些变量(hInstance
,commandLine
,hPrevInstance
等等。当您访问甚至修改这些内存区域时,您将面临破坏程序甚至整个系统的风险。再一次,这是访问越界的原因之一。
最后一行(允许重复注意,因为它很重要),这是依赖于实现的,并且在另一个平台甚至同一平台的不同版本上编译代码时可能会发生变化。
BTW,#import
不标准预处理器指示。它(最有可能)仅可用in Visual Studio 2017。不要再这样做了。我猜您基于该代码在Windows上使用VS 2017。
答案 1 :(得分:0)
您的定义数组和索引是
uint8_t arrOr [55];
uint8_t arr [55];
index = 119;
不在数组中,因此您需要减少索引值或增加数组大小,以便访问内存位置值,即垃圾或时间分段错误
// accessing array out of bounds
#include <stdio.h>
int main()
{
int arr[] = {1,2,3,4,5};
printf("arr [0] is %d\n",arr[0]);
printf("arr[10] is %d\n",arr[10]);
// allocation memory to out of bound
// element
arr[10] = 11;
printf("arr[10] is %d\n",arr[10]);
return 0;
}
输出:运行时错误:分段错误(SIGSEGV)
重点:
- 在C编程中保留在数组的边界内,同时使用数组来避免任何此类错误。 -C ++但是提供了std :: vector类模板,它不需要执行边界检查。向量还有std :: at()成员函数,它可以执行边界检查。
对于java,您可以使用
轻松处理此异常java.lang.ArrayIndexOutOfBoundsException