指针:尝试通过添加大量数字来取消引用指针时读取访问冲突
Pointers: Read access violation when trying to dereference pointer by adding a large number
我正在尝试更多地探索指针,下面是我正在尝试的一段代码示例
有效:
int *arth, art;
art = 100;
arth = &art;
printf("arth address is %p arth+1 value is %d", arth, *(arth + 1));
现在,如果我尝试向 arth 添加大量数字,我会遇到读取访问冲突
这不是:
printf("arth address is %p arth+1 value is %d", arth, *(arth + 1000));
错误:
Exception thrown: read access violation.
arth was 0xC9C5EFF964. occurred
提问:
有人可以解释为什么这在加 1 时起作用而不是在加 1000
时起作用吗
因为这个 *(arth + 1)
调用 未定义的行为!
未定义的行为是指程序可能会出现意外行为。在您的情况下,它 可能 在您的第一个代码片段和第二个代码片段中起作用。或者,今天它可能对这两种情况都不起作用。明天就可以了。在你的机器上它可能工作,在我的..也许不!详细了解 UB。
您正在访问您的指针不应访问的内存。
当你加 1 时,你可能是(不)幸运的,你访问了你的程序 拥有的内存 ,因此你逃脱了警察的惩罚(OS).
当您添加 1000 时,您超出了程序的 段 ,导致段错误或访问冲突(随便你说!)。
可视化:
你的行为就像 arch
指向一个数组,当 array[i]
有效时,array[i + 1]
也有效(假设 i + 1 不大于或等于数组的尺寸)。
然而,arch
只是指向一个变量,仅此而已!
C让你整天做指针运算,结果你自己负责。在您的情况下,两个增量在语法等方面都是有效的,但调用未定义行为,这是一个逻辑错误(可以说这会导致运行时无效)。
arth
指向 int
的单个实例。将任何非零值添加到 arth
并随后取消引用该新指针值会读取原始 int
范围之外的内存位置。这会调用 undefined behavior.
对于未定义的行为,任何事情都可能发生。您的程序可能会崩溃,可能会输出奇怪的结果,或者看起来工作正常。您没有在 *(arth + 1))
案例中崩溃但在 *(arth + 1000))
案例中崩溃就是一个例子。
仅仅因为程序没有崩溃并不意味着它没有做错什么。
Arth 指向一个整数,但是 arth+1 没有指向您在代码中定义的任何地方,arth+1000 也没有。
C 实际上允许您将指针递增到超过内存分配的一个元素,因此 arth+1 在技术上是允许的,但 arth+1000 不是。 arth+1000 的行为是未定义的,所以任何事情都有可能发生。在你的情况下,这是一个错误。
*(arth + 1000), 类似于 arth[1000] 而 (arth+1) 等于 arth[1].(arth + 1000) 其中您没有在内存中分配或初始化任何 space,因此编译器将抛出未定义的行为,并且没有分配到该位置的数据。
无论是 *(arth + 1) 还是 (arth +1000) 都是无效的,因为您正在访问未在 all.It 分配的内存可能由于 valgrind 未定义 behavior.Run 而工作并检查 valgrind 日志,无论是 *(arth +1) 还是 *(arth +1000),它总是会报告无效读取。当您添加任何与指针相关的代码时,总是 运行 valgrind。
我正在尝试更多地探索指针,下面是我正在尝试的一段代码示例
有效:
int *arth, art;
art = 100;
arth = &art;
printf("arth address is %p arth+1 value is %d", arth, *(arth + 1));
现在,如果我尝试向 arth 添加大量数字,我会遇到读取访问冲突
这不是:
printf("arth address is %p arth+1 value is %d", arth, *(arth + 1000));
错误:
Exception thrown: read access violation. arth was 0xC9C5EFF964. occurred
提问:
有人可以解释为什么这在加 1 时起作用而不是在加 1000
因为这个 *(arth + 1)
调用 未定义的行为!
未定义的行为是指程序可能会出现意外行为。在您的情况下,它 可能 在您的第一个代码片段和第二个代码片段中起作用。或者,今天它可能对这两种情况都不起作用。明天就可以了。在你的机器上它可能工作,在我的..也许不!详细了解 UB。
您正在访问您的指针不应访问的内存。
当你加 1 时,你可能是(不)幸运的,你访问了你的程序 拥有的内存 ,因此你逃脱了警察的惩罚(OS).
当您添加 1000 时,您超出了程序的 段 ,导致段错误或访问冲突(随便你说!)。
可视化:
你的行为就像 arch
指向一个数组,当 array[i]
有效时,array[i + 1]
也有效(假设 i + 1 不大于或等于数组的尺寸)。
然而,arch
只是指向一个变量,仅此而已!
C让你整天做指针运算,结果你自己负责。在您的情况下,两个增量在语法等方面都是有效的,但调用未定义行为,这是一个逻辑错误(可以说这会导致运行时无效)。
arth
指向 int
的单个实例。将任何非零值添加到 arth
并随后取消引用该新指针值会读取原始 int
范围之外的内存位置。这会调用 undefined behavior.
对于未定义的行为,任何事情都可能发生。您的程序可能会崩溃,可能会输出奇怪的结果,或者看起来工作正常。您没有在 *(arth + 1))
案例中崩溃但在 *(arth + 1000))
案例中崩溃就是一个例子。
仅仅因为程序没有崩溃并不意味着它没有做错什么。
Arth 指向一个整数,但是 arth+1 没有指向您在代码中定义的任何地方,arth+1000 也没有。
C 实际上允许您将指针递增到超过内存分配的一个元素,因此 arth+1 在技术上是允许的,但 arth+1000 不是。 arth+1000 的行为是未定义的,所以任何事情都有可能发生。在你的情况下,这是一个错误。
*(arth + 1000), 类似于 arth[1000] 而 (arth+1) 等于 arth[1].(arth + 1000) 其中您没有在内存中分配或初始化任何 space,因此编译器将抛出未定义的行为,并且没有分配到该位置的数据。
无论是 *(arth + 1) 还是 (arth +1000) 都是无效的,因为您正在访问未在 all.It 分配的内存可能由于 valgrind 未定义 behavior.Run 而工作并检查 valgrind 日志,无论是 *(arth +1) 还是 *(arth +1000),它总是会报告无效读取。当您添加任何与指针相关的代码时,总是 运行 valgrind。