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

标签: 运行时 对象 | 发表时间:2011-10-25 22:55 | 作者:egmkang Xin
出处:http://www.cnblogs.com/

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

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,有兴趣的朋友研究一下

作者: egmkang 发表于 2011-10-25 22:55 原文链接

评论: 0 查看评论 发表评论


最新新闻:
· Chrome 15发布,改进“新标签页”(2011-10-26 14:34)
· 山东聊城18岁少年编写9000多款软件(2011-10-26 14:21)
· 在异国成功的投资者 Yuri Milner(2011-10-26 14:14)
· Twitter悄然测试可扩展时间线功能(2011-10-26 14:12)
· 英美等国要求谷歌提供用户数据:涉及数万账户(2011-10-26 14:07)

编辑推荐:最老程序员创业札记:全文检索、数据挖掘、推荐引擎应用52

网站导航:博客园首页  我的园子  新闻  闪存  小组  博问  知识库

相关 [运行时 对象] 推荐:

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

- Xin - 博客园-首页原创精华区
相信很多人碰到过一个问题,就是代码太多了,不知道在哪里把这个对象给修改掉了.这个其实有两种办法的.. 在调试的时候,可以下数据断点..   gdb有watch断点.比如gdb>watch *(int*)0x12433,要记住,如果想要一只监视这个数据,就要用地址,否则过了这个scope,数据断点就无效了,还有就是,监视的值如果用内置数据类型可以表达的话,是有硬件断点的,否则效率茫茫低......

Android 运行时权限库

- - DiyCode - 致力于构建开发工程师高端交流分享社区社区
在项目的 build.gradle中,添加:. 在app的 build.gradle中,添加:. 创建一个 PermissionCompat.Builder对象. 设置弹出框,当 shouldShowRequestPermissionRationale() 返回true的时候,即用户已经拒绝了一次,给用户提示一个解释信息,为什么需要这个权限.

运行时动态修改注解

- - ITeye博客
      由于当前项目采用了分表策略,故一个实体会对应多个相同结构的表. 只是映射的表名不一样而已~项目又使用憨包儿呢特,让我采用原生SQL总感觉不是那么爽,咋办呢. 第一念头就是如果能够动态映射就好啦,也就是现在想查table1只需将实体对应的table映射为table1即可. 本质上修改字节码,重新加载类即可,也就是所谓的字节码增强功能~  看都看不懂字节码咋个修改呢.

Mozilla Shumway:基于 HTML5 的 Flash 运行时

- - ITeye资讯频道
Mozilla 近日正式发布了完全使用 HTML5 技术实现的 SWF 运行时环境 Shumway. 和Mozilla另一产品pdf.js 类似, Shumway 完全使用 HTML5 技术构建,实现了一个 Flash 的图像、音频、视频以及 Actionscript 的 1 至 3 版本的运行时环境.

Java运行时的内存模型

- - CSDN博客编程语言推荐文章
每个线程单独的数据区(线程间不共享). 每个线程都有一片单独的内存区域,这里面包含:程序计数器(program counter register),JVM栈和本地方法栈(Native Method Stack). 当一个新的线程被创建的时候,这片内存就已经被分配出来了. 程序计数器:为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各线程之间的计数器互不影响,独立存储.

自己动手实现springboot运行时执行java源码(运行时编译、加载、注册bean、调用)

- - 掘金 后端
  看来断点、单步调试还不够硬核,根本没多少人看,这次再来个硬核的. 依然是由于apaas平台越来越流行了,如果apaas平台选择了java语言作为平台内的业务代码,那么不仅仅面临着IDE外的断点、单步调试,还面临着为了实现预览效果,需要将写好的java源码动态的装载到spring容器中然后调用源码内的某个方法.

javascript对象转json

- - JavaScript - Web前端 - ITeye博客
把javascript对象转成json. 已有 0 人发表留言,猛击->> 这里<<-参与讨论. —软件人才免语言低担保 赴美带薪读研.

使用gdb调试运行时的程序小技巧

- - 淘宝核心系统团队博客
转载请注明:转载自淘宝核心系统团队博客,谢谢. 原文链接地址: 使用gdb调试运行时的程序小技巧. 下面介绍我调试时经常遇到的三种问题,如果大家也有类似的问题交流一下解决方法:. 情景1:在不中止程序服务的情况下,怎么调试正在运行时的程序. 情景2:需要同时看几个变量的值或者批量查看多个core文件的堆栈信息怎么办.

JAVA内存结构之运行时数据区域

- - Java - 编程语言 - ITeye博客
1       内存区域. 1.1              运行时数据区域. Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域. 这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则是依赖用户线锃的启动和结束而建立和销毁.

Android下个版本将默认使用ART运行时

- - 博客园_新闻
ART 运行时已包含在 Android4.4 KitKat 中,我们都知道它最终将会替代旧的低效的 Dalvik 运行时. ART 在应用安装时就预编译字节码到机器语言,这一机制叫 Ahead-Of-Time (AOT)编译.