程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> [C++]運行時,如何確保一個對象是只讀的

[C++]運行時,如何確保一個對象是只讀的

編輯: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   www.2cto.com

 

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

 

/**********************************************************************

 * 機械教條主義

 

 * Email:         egmkang [at] 163.com

 * QQ Group:  20240291(慎入,可能沒人打理)

 * Weibo:        http://weibo.com/egmkang

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved