当指针过大时会发生什么?

3
在C++或C中,如果将指针设置为超出内存边界的值,会发生什么?下面是可能导致这种情况发生的代码:
int* ptr = 0;
while (true) {
    ptr += 1; // eventually this will go out of bounds of the memory ... unless there is an overflow.
    *ptr = 10; // just give it a value, why not?
}

发生了什么?当指针超出16字节内存的范围时,它会从0xF翻转到0x0吗?它是否继续计数并且*ptr = 10;这一行会导致计算机崩溃?

我不至于蠢到去尝试,但我非常好奇。


2
“我不傻到去尝试,但我非常好奇。” - 只是试试吧。这并不能替代一个正确的答案,但如果你在任何主要操作系统上运行,你不会造成任何损害。 - user820304
1
是的,指针仅仅是值容器,它只会翻转。然而,在 while 循环体中的第二行有 100% 的未定义行为机会。 - Hatted Rooster
4
未定义行为啊oy。 - user975989
1
我不傻到去尝试,但我非常好奇。这就是虚拟机的用途!想象一下,在计算机模拟中可以做任何事情的可能性。 - milleniumbug
2
去吧,大胆地进行虚拟内存的实验从来没有害死任何人(除了进程。当你在不合适的内存位置乱写时,进程确实可能会被终止)。 - Petr Skocik
6个回答

10

未定义行为。

事实上,将指针递增至原始指向对象的末尾后一个元素以上的位置会导致未定义行为。(您可以构造指向对象末尾刚好过去一位的指针,但不能超过这一范围。)(所讨论的对象是数组,非数组对象被视为只有一个元素的数组。)

这意味着语言标准没有规定可能发生的情况。它可能会“工作”,也可能会使您的程序崩溃,并可能产生任何您的程序能够产生的症状。

实际上,行为可能因系统而异。增加指针可能会像增加无符号整数一样:更新值而不会引起任何可见问题。如果尝试解引用指针,则结果取决于系统如何管理内存。

底线:未定义行为是未定义的。


6
您完全可以让指针指向对象之外的位置。 - EOF
2
@EOF 指的是仅仅超出(对象的)末尾。 - Daniel Jour
2
@EOF:非常正确。我的措辞非常拙劣,甚至是错误的。我已经修正了它。 - Keith Thompson

3

在C++中,访问超出您分配的内存范围(通过newmalloc等方式)是未定义的行为,因此不要指望一切都会顺利进行。

实际上,在大多数平台上,增加指针超过物理限制是由平台定义的,它最终会翻转;访问它可能导致崩溃。

对于大多数现代操作系统,尝试读取或写入进程未分配的内存将导致访问冲突或分段错误。


1
C/C++语言并非为现有的系统/机器定义,而是一个抽象的黑盒子(尽管它不会忽略现实)。你正在要求未定义的行为(一些现有的系统/机器可能会按照你的期望执行)。

1

在我所了解的常见系统(主要或唯一是我的系统),指针的行为非常类似于unsigned long

int main(){
    char* p = NULL;
    printf("%p\n", p);
    printf("%p\n", --p);
}

输出:
(nil)
0xffffffffffffffff

但我想理论上可能发生各种奇异的事情。


1
指针仅对对象或“一次通行”有效。
int x;
int *p = &x;
p++;
p++; // invalid
int y[5];
p = &y[4];
p = &y[5];
p = &y[6]; // invalid

指针可以被赋予一个空指针值;
p = NULL;

指针可以指向函数。

就是这样。将指针分配给其他值是未定义行为(UB),例如:

int* ptr = 0;
ptr += 1;  // UB  (NULL is not a pointer to a valid object, so "1 pass" is UB)

0

在我看来,你的指针不会有任何问题,如果你只是保存指针,什么也不会发生,但是当你尝试解引用/访问它时,我相信你的代码最终会出现访问冲突并导致程序崩溃。或者如果它是一个有效的指针,它可能会修改其他数据,可能会修改另一个变量的内容。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接