-6

我可以在 C/C++ 中设置/禁用普通数组的最后几个元素的读取(或写入)访问权限吗?由于我不能使用其他进程的内存,我怀疑这是可能的,但如何?我用谷歌搜索但找不到。

如果可以,怎么做?

因为我想尝试这样的事情:

SetPrivilage(arr,LAST_5_ELEMENTS,false);

try
{
    for(int i=0;;i++) //without bound checking. i know its evil. just trying if it is possible
    {
        arr[i]++;     //array is 1-billion elements
    } 
}
catch(int catch_end_of_array)
{
    printf("array-inc complete");
}

Memory:

|start of array |00|01|02|03|04|05|06|07|..|..|1B|start of protected page|xx|xx|xx|xx|xx|xx|xx|xx|xx|xx|xx|xx|xx|

假设我学会了如何保护页面,那么我如何在页面附近声明一个数组,以便数组端点位于页面旁边。?

4

3 回答 3

3

这不能以便携式方式完成,并且取决于您的操作系统。我怀疑这在任何地方都不可能,因为内存保护通常在更粗略的级别上运行(例如,Linux 有mprotect系统调用,但这只能保护整个pages(通常是 4k 块),而不是任意范围。

于 2012-09-04T10:08:16.997 回答
2

如果您使用操作系统接口保护页面,那么您可以放置​​一个数组,以便数组在保护开始的地方结束。您必须通过设置的指针(例如,int *p)来指定数组,而不是将其声明为数组(例如,int p[40]),因为大多数 C 实现不给您指定数组地址的方法。

由于大多数系统内存保护的粒度,您通常只能将阵列的一端与保护边界对齐。因此,这不是保护数组边界的普遍有用的机制。我已将其用于测试目的,分别测试两端:

  • 对齐数组,使其末端紧靠受保护内存的开头。执行测试。
  • 对齐一个数组,使其开始与受保护内存的结尾相邻。执行测试。

因此,如果被测试的例程在数组之前或之后不正确地访问内存,那么其中一个测试将失败。

于 2012-09-04T10:54:34.943 回答
1

我假设你arr是一个 POD(普通旧数据)数组。您可以在 C++ 中使其成为一个类并重载它operator[]以进行运行时索引检查。

你通常不能做你想做的事,如果可以的话,它会强烈地依赖于实现和操作系统。

在 Linux 上,对数据的访问权限与虚拟内存映射有关。这与带有mprotect(2)系统调用的mmap(2) 和 munmap(2)有关。这些调用以页面级别的粒度工作(页面通常为 4Kbytes,并且 4Kbytes 对齐)。

你可以做一些淘气的把戏,比如mmap-ing 一个大区域,mprotect它的最后一页,并做不可移植的指针算法来计算arr指针。这很恶心,所以不要这样做。像这样SIGSEGV使用基于脏mmap的技巧进行捕捉不是很便携,而且可能不是很有效。并且信号处理程序不能抛出 C++ 异常。

于 2012-09-04T10:08:08.433 回答