我希望将堆栈上对象的访问属性设置为只读,但只要我调用mProtect,该进程就会崩溃.大致代码如下:

constexpr int kPageSize = 4096;
CHECK_EQ(kPageSize, sysconf(_SC_PAGE_SIZE));
volatile char padding1[kPageSize] = {0};
NetDataHead head;
volatile char padding2[kPageSize] = {0};

// ...
auto align_down_4k_ptr = steel::AlignDownPointer(&head, kPageSize);
CHECK_EQ(reinterpret_cast<std::uint64_t>(align_down_4k_ptr) % kPageSize, 0);
if (auto rc = mprotect(align_down_4k_ptr, kPageSize, PROT_READ); rc != 0) {  // A
  LOG_F("Failed to mprotect ptr: %p, rc: %d", align_down_4k_ptr, rc);
}

// Read-only codes ...

if (auto rc = mprotect(align_down_4k_ptr, kPageSize, PROT_READ | PROT_WRITE); rc != 0) {
  LOG_F("Failed to mprotect ptr: %p, rc: %d", align_down_4k_ptr, rc);
}

程序直接在A点崩溃,A点是第一个mprotect调用的位置.

通过参考手册,这似乎不会导致Linux崩溃.有人知道为什么会发生这种事吗?

man 2 mprotect

我想要使用m保护来保护堆栈上的"Head" struct .

推荐答案

手册页说这是允许的,事实上,内核似乎将堆栈区域设置为只读.然而,内存保护硬件的粒度很粗,通常为4K、8K或更高,因此堆栈的其他区域也受到保护,例如用于保存寄存器的空间,这会在系统调用返回时立即导致崩溃.

您通过定义2个填充数组来隔离数据的try 不起作用.连续的定义不保证连续的实例化.如果不使用填充数组,它们可能根本不会被实例化.让它们达到volatile无关紧要.

为此,您应该定义一个更大的 struct 或使用MMPAP内存块.

C++相关问答推荐

为什么下面的递归基本情况在C中不起作用?

字符串令牌化xpath表达式

需要大整数和浮点数.使用long long int和long double

如何正确地索引C中的 struct 指针数组?

无效指针值在函数调用之间莫名其妙地改变

在传统操作系统上可以在虚拟0x0写入吗?

为静态库做准备中的奇怪行为

Square不与Raylib一起移动

为什么指针运算会产生错误的结果?

用C++从外部ELF符号读取值

为什么我从CSV文件中进行排序和搜索的代码没有显示数据的所有结果?

C11/C17标准允许编译器清除复合文字内存吗?

如果格式字符串的内存与printf的一个参数共享,会发生什么情况?

使用Open62541向OPCUA服务器发送读请求时内存泄漏

c程序,让用户输入两类数字,并给出输出用户输入多少个数字

C中的char**v*char[]

将某些内容添加到链接列表时,列表中的其他项将使用最后添加的项的名称

存储和访问指向 struct 的指针数组

未为同一文件中的函数执行DirectFunctionCall

使用fread()函数读取txt文件