egmkang

       "新的代数语言每5年就走红和过时,而我想要强调的是永恒的概念." ------By Knuth

[C++]运行时,如何确保一个对象是只读的

相信很多人碰到过一个问题,就是代码太多了,不知道在哪里把这个对象给修改掉了.这个其实有两种办法的.

1. 在调试的时候,可以下数据断点.

  gdb有watch断点.比如gdb>watch *(int*)0x12433,要记住,如果想要一只监视这个数据,就要用地址,否则过了这个scope,数据断点就无效了,还有就是,监视的值如果用内置数据类型可以表达的话,是有硬件断点的,否则效率茫茫低.....

2. 运行的时候,本文主要讲这个.

  先来回顾一下,我们都知道一个exec,都有好几个段,比如代码段,数据段等.这些段是有读写属性的,例如代码段只可以读,栈段是可以读写~~.那么我们就想把一个对象塞到一个不可以写的段里面,比如.text段....(事实上,我塞进去过,只不过会有警告)

  这个异常暴力,而且预留余地太小,不太适合.

  现在操作系统都是段模式+分页模式来管理内存的.段模式走不通,换页模式,找个办法设置内存页的属性~~.

  非常幸运,Linux下面有mprotect系统调用,可以运行时设置内存页的读写属性,唯一的要求是内存需要4K对齐,浪费了一点.

  OK,让我们来看mprotect的man page:http://linux.die.net/man/2/mprotect

  签名很简答:int mprotect(const void *addr, size_t len, int prot);

  一个地址,一个内存的长度,另外就是读写属性,返回调用的结果,成功返回0,失败返回其他数字.

  顺便看看man page中的例子,里面有一个技巧,就是搞到一个4K对齐的内存~~ 通过 ( ptr + 4096 - 1 ) & ~(4096 - 1)搞到的

  

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/mman.h>
#include <limits.h>    /* for PAGESIZE */
#ifndef PAGESIZE
#define PAGESIZE 4096
#endif
int
main(void)
{
    char *p;
    char c;
    /* Allocate a buffer; it will have the default
       protection of PROT_READ|PROT_WRITE. */
    p = malloc(1024+PAGESIZE-1);
    if (!p) {
        perror("Couldn't malloc(1024)");
        exit(errno);
    }
    /* Align to a multiple of PAGESIZE, assumed to be a power of two */
    p = (char *)(((int) p + PAGESIZE-1) & ~(PAGESIZE-1));
    c = p[666];         /* Read; ok */
    p[666] = 42;        /* Write; ok */
    /* Mark the buffer read-only. */
    if (mprotect(p, 1024, PROT_READ)) {
        perror("Couldn't mprotect");
        exit(errno);
    }
    c = p[666];         /* Read; ok */
    p[666] = 42;        /* Write; program dies on SIGSEGV */
    exit(0);
}

至此,我们就可以运行时,保证一个对象不可以写,写的话,core掉:-D

PS:

希望windows下也有类似的系统调用,Windows下有VirtualProtect,有兴趣的朋友研究一下

/**********************************************************************
 * 机械教条主义
 *
 * From:          http://www.cnblogs.com/egmkang/
 * Email:         egmkang [at] 163.com
 * QQ Group:  20240291(慎入,可能没人打理)
 * Weibo:
        http://weibo.com/egmkang
 *
 **********************************************************************/

标签: C++, mprotect

posted on 2011-10-25 22:55 egmkang 阅读(1216) 评论(8) 编辑 收藏

评论

#1楼 2011-10-26 19:49 OwnWaterloo      

页大小最好不要简单假定为4096哦亲~
有个sysconf还是啥的函数来着……

既然都用mprotect(posix)了,也可以用valloc或者posix_memalign了亲~
 回复 引用 查看   

#2楼[楼主] 2011-10-26 22:31 egmkang      

引用OwnWaterloo:
页大小最好不要简单假定为4096哦亲~
有个sysconf还是啥的函数来着……
既然都用mprotect(posix)了,也可以用valloc或者posix_memalign了亲~

我看过了,x64下面也是4K的页,也有一些操作系统可能不是4K的页,没记错的话,有Solaris貌似不是4K的.(以前上大学的时候看操作系统,上面说的,具体的早忘得差不多了)
不过动态获取页大小确是不错,更通用一些.
你确实是熟读一切文档啊....(我最近才开始看APUE啊,恶补)
老来踢场子,却从来都不写blog,让小生去膜拜
:-D  回复 引用 查看   

#3楼 2011-10-26 23:07 OwnWaterloo      

@egmkang
也不是一切文档……
因为以前做过一个"可执行内存分配器",所以与这有关的文档就需要看……
mmap/mprotect肯定算~
可执行保护粒度是页,所以sysconf也算……
类似的valloc/posix_memalign也……
x64貌似可配置的……

blog我打算自己做一个……
需要什么功能我就可以自己动手,不必等着博客服务提供了……
不过这方面不熟悉啊,而且gae又被锁了半年多了…… 很没动力……
 回复 引用 查看   

#4楼[楼主] 2011-10-26 23:47 egmkang      

引用OwnWaterloo:
@egmkang
也不是一切文档……
因为以前做过一个"可执行内存分配器",所以与这有关的文档就需要看……
mmap/mprotect肯定算~
可执行保护粒度是页,所以sysconf也算……
类似的valloc/posix_memalign也……
x64貌似可配置的……

blog我打算自己做一个……
需要什么功能我就可以自己动手,不必等着博客服务提供了……
不过这方面不熟悉啊,而且gae又被锁了半年多了…… 很没动力……

哟西,cppblog那边有一个家伙自己用lisp做了一个blog
你难道也要效仿??  回复 引用 查看   

#5楼 2011-10-27 00:29 OwnWaterloo      

@egmkang
应该不太一样。

首先我熟悉的是elisp(因为要用emacs -_-)
如果有机会,想用scheme;但不太喜欢common lisp(Kevin Lynx用的就是cl)……

再者。。。 我并不想做一个"blog程序"。
比如cnblogs, 它有自己的编辑器, 貌似还支持metablog api, 还有一些如备份什么的功能。
再比如wordpress, 貌似就是把它放在vps的什么什么目录。
貌似Kevin Lynx的是这两种之一……

而我所谓的blog…… 其实就是本地上的一些笔记之类的。
并且将来也不会用blog程序附带的编辑器,始终都只会用emacs/vim编辑本地的html/rst/tex文档。
本体始终是本地笔记, 只是顺带想找个地方将可以公开的部分放上去, 顺便实现一些评论啊,同名文件消歧义(维基百科那样)啊什么的……

感觉很折腾…… 但重要的东西不由自己控制心理又很慌啊……
有没有什么地方我想错了 >_< ?
 回复 引用 查看   

#6楼[楼主] 2011-10-27 09:54 egmkang      

@OwnWaterloo

scheme只在SCIP里面看过,看的蛮头疼的...
感觉你这像是Knuth啊.Knuth的主页就是纯HTML的吧,之前要出HTML5,他貌似还在叫,不要更新,我根本没时间把现在的html转化成HTML5的....
高玩啊
 回复 引用 查看   

#7楼 2011-10-27 10:11 OwnWaterloo      

@egmkang
即使支持html5的浏览器出现了,也不会放弃对目前的html支持吧?
没必要转啊……

最近上船的人好多…… 高爷爷要hold住!!!
 回复 引用 查看   

#8楼[楼主] 2011-10-27 11:36 egmkang      

引用OwnWaterloo:
@egmkang
即使支持html5的浏览器出现了,也不会放弃对目前的html支持吧?
没必要转啊……

最近上船的人好多…… 高爷爷要hold住!!!

哈,我看这个样子,书是写不完了....
多少人都上船了....  回复 引用 查看