C - 指针如何覆盖局部 const 内存块而不是全局 const 内存块?
C - How can a pointer overwrite a local const block of memory but not the global const block of memory?
上次我问如何通过绕过编译器不覆盖 const
内存的承诺在程序中生成 segmentation
错误。用户 Marco Bonelli 描述了以下方法,效果很好。
const static int global = 123;
int main(void) {
int *ptr = (int *)&global;
*ptr = 456;
// or, equivalent
const int *ptr2 = &global;
*(int *)ptr2 = 456;
}
无论哪种方式,我都能够生成分段错误。
-
int *ptr = (int *)&global;
*ptr = 456;
-
const int *ptr2 = &global;
*(int *)ptr2 = 456;
现在我的问题是,是什么阻止了指针写入 global const
内存块而不是 local const
内存块。例如,在下面的代码中,我能够毫无问题地写入 const
内存块。
#include <stdio.h>
int main(void) {
const int local = 123;
int *ptr = (int *)&local;
*ptr = 456;
// how come this be possible?
printf("%d\n", local); // -> 456
// or, equivalent
const int *ptr2 = &local;
*(int *)ptr2 = 512;
// how come this be possible?
printf("%d\n", local); // -> 512
}
我很好奇这是怎么发生的。请赐教
如果重要的话,我正在使用 gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
。
after the termination of the program what exactly happens to that block?
您的进程 virtual memory 会发生什么由操作系统决定。当程序终止时,操作系统将清除为您的程序分配的所有内存,无论这些内存用于什么。 const
的概念与此无关
Was the compiler able to remove that const qualifier from that particular block? Can I be able to overwrite that block of memory, if so how can I do that explicitly?
您不能更改变量的声明方式。它在整个生命周期中都保持这种状态。您将无法做到这一点,即便如此,也 undefined behavior 尝试这样做。
What if I need to overwrite a const
block of memory? Is there any way to do that?
如果您需要这样做,那么您编写的任何程序的逻辑都是有缺陷的。你不能也不应该这样做。这是未定义的行为,在最好的情况下会用 segmentation fault.
杀死你的程序
好的,如果你真的想用写入 const
变量导致的分段错误终止你的程序,假设你的编译器将全局 const
变量放在只读部分(例如 .rodata
),那么以下内容就足够了:
const static int global = 123;
int main(void) {
int *ptr = (int *)&global;
*ptr = 456;
// or, equivalent
const int *ptr2 = &global;
*(int *)ptr2 = 456;
}
您需要“丢弃”const
限定符,以便编译器不会将其视为错误。同样,这仅在编译器将 global
放入 read-only 部分(标准不要求)时才有效。如果这不会导致分段错误,那么这意味着您的编译器不会将所有 const
变量放入 read-only 部分。
这完全取决于实施。例如,const
裸机 ARM uC 上的数据存储在 FLASH 存储器中。你可以写到那里,但它根本没有作用。
托管系统的行为会因 OS、其版本和硬件而异。
How can I overwrite a const block of memory
只要你想写就不要声明它const
。如果你尊重给编译器的承诺。
如果只是初学者的好奇心,除了试验没有别的办法。实验、调试并尝试解释结果。
编辑。
在最常见的实现中:
constant local(自动变量是在堆栈上创建的,不受操作系统保护以防止写入 - 你没有得到段错误。
常量全局(静态存储)变量放置在 .rodata
段中,该段受操作系统保护以防止写入 - 您遇到了段错误。
上次我问如何通过绕过编译器不覆盖 const
内存的承诺在程序中生成 segmentation
错误。用户 Marco Bonelli 描述了以下方法,效果很好。
const static int global = 123;
int main(void) {
int *ptr = (int *)&global;
*ptr = 456;
// or, equivalent
const int *ptr2 = &global;
*(int *)ptr2 = 456;
}
无论哪种方式,我都能够生成分段错误。
-
int *ptr = (int *)&global; *ptr = 456;
-
const int *ptr2 = &global; *(int *)ptr2 = 456;
现在我的问题是,是什么阻止了指针写入 global const
内存块而不是 local const
内存块。例如,在下面的代码中,我能够毫无问题地写入 const
内存块。
#include <stdio.h>
int main(void) {
const int local = 123;
int *ptr = (int *)&local;
*ptr = 456;
// how come this be possible?
printf("%d\n", local); // -> 456
// or, equivalent
const int *ptr2 = &local;
*(int *)ptr2 = 512;
// how come this be possible?
printf("%d\n", local); // -> 512
}
我很好奇这是怎么发生的。请赐教
如果重要的话,我正在使用 gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
。
after the termination of the program what exactly happens to that block?
您的进程 virtual memory 会发生什么由操作系统决定。当程序终止时,操作系统将清除为您的程序分配的所有内存,无论这些内存用于什么。 const
的概念与此无关
Was the compiler able to remove that const qualifier from that particular block? Can I be able to overwrite that block of memory, if so how can I do that explicitly?
您不能更改变量的声明方式。它在整个生命周期中都保持这种状态。您将无法做到这一点,即便如此,也 undefined behavior 尝试这样做。
What if I need to overwrite a
const
block of memory? Is there any way to do that?
如果您需要这样做,那么您编写的任何程序的逻辑都是有缺陷的。你不能也不应该这样做。这是未定义的行为,在最好的情况下会用 segmentation fault.
杀死你的程序好的,如果你真的想用写入 const
变量导致的分段错误终止你的程序,假设你的编译器将全局 const
变量放在只读部分(例如 .rodata
),那么以下内容就足够了:
const static int global = 123;
int main(void) {
int *ptr = (int *)&global;
*ptr = 456;
// or, equivalent
const int *ptr2 = &global;
*(int *)ptr2 = 456;
}
您需要“丢弃”const
限定符,以便编译器不会将其视为错误。同样,这仅在编译器将 global
放入 read-only 部分(标准不要求)时才有效。如果这不会导致分段错误,那么这意味着您的编译器不会将所有 const
变量放入 read-only 部分。
这完全取决于实施。例如,const
裸机 ARM uC 上的数据存储在 FLASH 存储器中。你可以写到那里,但它根本没有作用。
托管系统的行为会因 OS、其版本和硬件而异。
How can I overwrite a const block of memory
只要你想写就不要声明它const
。如果你尊重给编译器的承诺。
如果只是初学者的好奇心,除了试验没有别的办法。实验、调试并尝试解释结果。
编辑。
在最常见的实现中:
constant local(自动变量是在堆栈上创建的,不受操作系统保护以防止写入 - 你没有得到段错误。
常量全局(静态存储)变量放置在
.rodata
段中,该段受操作系统保护以防止写入 - 您遇到了段错误。