- 主题:请问C能否做到编译时按const检查变量,但运行时可按照普通变量
定义一个指向这个变量的常量指针,对外只暴露这个常量指针就行了
【 在 lexluthor 的大作中提到: 】
: 就是类似 const uint8_t tag[16]; 的变量
: 打算在初始化赋值的时候用类型转换赋值 memcpy((uint8_t *)tag, "0123456789012345", sizeof(tag));
: 但运行时直接 Segmentation fault 了,valgrind 报告如下错误:
: ...................
--
FROM 223.104.7.*
#include <stdint.h>
#include <cstring>
int main() {
const uint8_t tag[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5'};
uint8_t* tagPtr = const_cast<uint8_t*>(tag);
memcpy(tagPtr, "0123456789012345", sizeof(tag));
// 现在 tag 的值已经被修改了
return 0;
}
gpt3.5回答
【 在 lexluthor 的大作中提到: 】
: 对 对 对, 为了工作更有意义(不可替代), 必须随时在代码用一些高深的技术.
--
FROM 114.249.20.*
不带OS或简单的RTOS这样差不多可以,win或linux这个地址是只读,会报错
【 在 gfkid 的大作中提到: 】
: #include <stdint.h>
: #include <cstring>
:
: int main() {
: const uint8_t tag\[16\] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
: ..................
发自「今日水木 on 23013RK75C」
--
FROM 111.201.152.*
嗯我转给gpt3.5了,回答如下
如果你在使用操作系统(如Windows或Linux)时遇到了只读地址的错误,那可能是由于操作系统的内存保护机制导致的。在这种情况下,你需要使用操作系统提供的特定机制来修改只读内存。
在Windows和Linux上,操作系统会将只读内存映射为只读页面,以防止对其进行修改。如果你想要修改这些只读内存,你需要使用操作系统提供的函数来更改内存页面的保护属性。
在Windows上,你可以使用 `VirtualProtect` 函数来更改内存页面的保护属性。以下是一个示例代码:
```cpp
#include <Windows.h>
int main() {
const uint8_t tag[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5'};
uint8_t* tagPtr = const_cast<uint8_t*>(tag);
DWORD oldProtect;
VirtualProtect(tagPtr, sizeof(tag), PAGE_READWRITE, &oldProtect);
memcpy(tagPtr, "0123456789012345", sizeof(tag));
// 现在 tag 的值已经被修改了
return 0;
}
```
在Linux上,你可以使用 `mprotect` 函数来更改内存页面的保护属性。以下是一个示例代码:
```cpp
#include <sys/mman.h>
#include <cstring>
int main() {
const uint8_t tag[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5'};
uint8_t* tagPtr = const_cast<uint8_t*>(tag);
size_t pageSize = sysconf(_SC_PAGESIZE);
uintptr_t addr = reinterpret_cast<uintptr_t>(tagPtr);
uintptr_t pageStart = addr & ~(pageSize - 1);
mprotect(reinterpret_cast<void*>(pageStart), sizeof(tag), PROT_READ | PROT_WRITE);
memcpy(tagPtr, "0123456789012345", sizeof(tag));
// 现在 tag 的值已经被修改了
return 0;
}
```
请注意,这些代码在操作系统上使用特定的函数来修改内存保护属性,因此在不同的操作系统和平台上可能会有所不同。你需要根据你的操作系统和平台文档来查找适合的函数,并确保正确使用它们。
另外,请注意修改只读内存可能会导致不可预测的行为和系统不稳定性。请确保你明确了解你所做的更改,并在进行此类操作时谨慎。
【 在 yhwac 的大作中提到: 】
: 不带OS或简单的RTOS这样差不多可以,win或linux这个地址是只读,会报错
: 发自「今日水木 on 23013RK75C」
--
FROM 114.249.20.*
曾经用过mprotect()尝试寻找过一个bug,弄成只读后那个地方100%炸,不弄只读的话偶尔炸。
但是修改的地方太多,头大,不想改。
你猜我后来怎么干的,就是那块空间我不用了,我再找块地方,然后就基本不怎么炸了。
在那个地方留了一大块注释,不知道谁接手了那坨代码,我也是从别人手里接过来的。
【 在 gfkid 的大作中提到: 】
: 嗯我转给gpt3.5了,回答如下
: 如果你在使用操作系统(如Windows或Linux)时遇到了只读地址的错误,那可能是由于操作系统的内存保护机制导致的。在这种情况下,你需要使用操作系统提供的特定机制来修改只读内存。
: 在Windows和Linux上,操作系统会将只读内存映射为只读页面,以防止对其进行修改。如果你想要修改这些只读内存,你需要使用操作系统提供的函数来更改内存页面的保护属性。
: ...................
--
FROM 51.222.204.*
可以想象啊。学习了。
【 在 lexluthor 的大作中提到: 】
: 曾经用过mprotect()尝试寻找过一个bug,弄成只读后那个地方100%炸,不弄只读的话偶尔炸。
: 但是修改的地方太多,头大,不想改。
: 你猜我后来怎么干的,就是那块空间我不用了,我再找块地方,然后就基本不怎么炸了。
: ...................
--
FROM 114.249.20.*
又问了gpt4,似乎更好些
您遇到的问题是因为尝试修改了一个被声明为 `const` 的变量。在 C 语言中,`const` 关键字用于声明一个变量为常量,这意味着一旦初始化后,它的值就不能被修改。尝试修改一个 `const` 变量的值会导致未定义行为,通常会引发运行时错误,如您所遇到的 Segmentation Fault。
在您的例子中,`const uint8_t tag[16];` 声明了一个不可变的数组,然后您尝试使用 `memcpy` 来修改它的内容,这正是出错的原因。
如果您想在初始化时设置 `tag` 的值,但在之后的代码中保持它不可变,您可以考虑以下几种方法:
1. **初始化时赋值:**
直接在声明时初始化 `tag`,例如:
```c
const uint8_t tag[16] = "0123456789012345";
```
这样就在声明时设定了 `tag` 的值,并且之后不允许修改。
2. **使用指针:**
如果您需要在某个函数或代码块中修改 `tag`,可以考虑使用指向 `const` 的指针。例如,您可以声明一个非 `const` 数组,并使用一个指向 `const` 的指针来确保在其他地方不被修改:
```c
uint8_t tempTag[16];
memcpy(tempTag, "0123456789012345", sizeof(tempTag));
const uint8_t *tag = tempTag;
```
这样,`tempTag` 可以被修改,但通过 `tag` 指针访问的数据就不能被修改了。
3. **结构体封装:**
另一个方法是将数组封装在一个结构体中,并在需要修改值的函数或代码块内部进行修改,而在外部只暴露一个指向 `const` 的指针或引用。这可以通过控制访问权限来实现。
选择哪种方法取决于您的具体需求和代码的上下文。通常情况下,直接在声明时初始化是最简单和最安全的方式。如果您需要在程序的某个特定部分修改这个数组,那么使用指针或结构体封装可能更适合。
【 在 lexluthor 的大作中提到: 】
: 就是类似 const uint8_t tag[16]; 的变量
: 打算在初始化赋值的时候用类型转换赋值 memcpy((uint8_t *)tag, "0123456789012345", sizeof(tag));
: 但运行时直接 Segmentation fault 了,valgrind 报告如下错误:
: ...................
--
FROM 114.249.20.*
多谢, 结构体方法也很好用
【 在 gfkid 的大作中提到: 】
: 又问了gpt4,似乎更好些
: 您遇到的问题是因为尝试修改了一个被声明为 `const` 的变量。在 C 语言中,`const` 关键字用于声明一个变量为常量,这意味着一旦初始化后,它的值就不能被修改。尝试修改一个 `const` 变量的值会导致未定义行为,通常会引发运行时错误,如您所遇到的 Segmentation Fault。
: 在您的例子中,`const uint8_t tag[16];` 声明了一个不可变的数组,然后您尝试使用 `memcpy` 来修改它的内容,这正是出错的原因。
: ...................
--
FROM 206.189.38.*