指针行为异常

Pointer behaves strangely

我是一名编程和 C++ 新手。如果能提供一些帮助,我将不胜感激。

以下程序(在 c++ 中)在编译或 运行 时没有遇到任何问题:

int main()
{
    int b = 5;
    int*a = &b;
    *(a+5) = 6;
    return 0;

}

但根据我了解到的一切,它应该不起作用,因为 a 是指向单个变量的指针。我在这里错过了什么?

您的程序在编译时应该确实没有遇到任何问题。都是关于编译的有效代码。

但是它会在运行时遇到未定义的行为,因为 a+5 不是有效地址。

如果你想知道为什么要编译,你可以这样写代码:

int func( int * buf, size_t size )
{
    for( size_t i = 0; i < size; ++i )
    {
       *(buf + size) = static_cast<int>(i); // or (int)i in C
    }
}

int main()
{
   int buf[ 6 ];
   func( buf, 6 );
}

在您的代码中,a 是一个指向内存的指针。 a + 5 表示 a 指向的地址 5 "ints"。由于 a 指向单个整数 b,所以无法保证这样的地址。有趣的是,它被明确定义为引用 a+1,即使它指向内存中您不应读取或写入的位置。但是指针本身有一些保证,即它会大于 a 并且如果你从中减去 1 你会回到 a 如果你在它和 a 之间做一个 ptrdiff你会得到 1。但这只是 "one past the end" 的特殊 属性,它允许程序员指定内存范围。

是的,当您访问不在您的进程区域中的内存 space 时,它不应该工作,但也许没有人拥有该特定区域 ((a + 5)),这不会导致 运行时间非法内存访问还是可以的。因此它是一个 UB。

该程序确实有一个未定义的行为

int main()
{
    //This cause the loading of the "main" function to allocate memory for variable b
    //It could be in a memory page that was already allocated to the program
    //or in a new allocated page.
    int b = 5;

    //Here a just getting the address of variable b.
    int*a = &b;

    //This is the undefined behavior and can end up in two cases:
    // 1. If (a+5) value is in a memory space that is allocated to the application.
    //    Then no runtime error will happen, and the value will be writing there.
    //    probably dirting some other value, and can cause an undefined behavior later
    //    in the application execution.
    // 2. If (a+5) value is in a memory space that wasn't allocated to the application.
    //    the application will crash
    *(a+5) = 6;
    return 0;

}

现在,由于页面大小可能是 4096,而 b 在页面中的某处,*b+5 在大多数情况下仍然在同一页面中。如果你想挑战更多,将它从 5 更改为 5000 或更高,崩溃的机会将会增加。

只是添加到现有答案中。

访问权限

*(a+5) = a[5]

所以这个位置不是你分配的

以数组为例

int a[6];

您拥有从 a[0]a[5] 的有效访问权限,其中 a[5] 是数组的最后一个元素,任何进一步的访问权限如 a[6] 将导致未定义的行为因为那个位置不是你分配的。

同样,你只是分配了一个整数,如

int b=5;

int *a = &b;

a 是指向 &b 的指针,即 b.

的地址

所以对此的有效访问只是 a[0],这是您在堆栈上分配的唯一位置。

任何其他访问,如 a[1] a[2]... 等将导致未定义的行为。

访问结果是有效如果你有

int b[6];
int *a = b;

现在a[5]将给出数组最后一个元素的值b