关于C语言中的内存保护问题,高手进来讨论,绝对有价值,100分奉送。

joymouse 2005-09-11 10:16:59
假如函数中这样声名一个字符串:
void f(void)
{
char *pStr = "HELLO";
*pStr = 'Y';
......
}

这样会发生什么情况呢?其实编译器编译的时候总是会在代码的静态DATA区创建一个“HELLO”的字符串数据,然后把pStr指针指向这个静态数据区的地址,按理这样的静态数据应该相当于是const的,这个数据区的数据应该是不允许被修改的,属于常量字符串。问题就出来了,后面*pStr = 'Y'这一句,在VC编译下运行会出错,报非法的地址访问,得到正常保护;但是在BorlandC中编译后运行就没有抱错,运行后pStr变成了"YELLO"。
我想问的问题是:
1、VC对这个常量字符串的内存保护的依据是什么,我跟踪了VC的汇编语句,也没有发现什么特殊语法,但是在VC下单步运行到那儿就是要报内存访问非法,从而起到保护作用,不知道VC的保护原理是什么,这种保护是怎么实现的,为何在BorlandC下编译这种保护就没有。
2、同样的,如果在VC下声名了一个const类型的变量,当然如果企图去修改它则预编译的时候就会被发现,但是如果用一个指针指向这个const变量的地址骗过编译器,BorlandC下面就可以间接实现修改这个const的目的,而VC编译后运行就抱错,也就是runtime的时候骗不过去,当然,保护是合理的,但是不知道VC的这种保护是怎么实现的。代码如下:
const char cTest;
char *pTest;

pTest = &cTest;
*pTest = 'A'; //这样间接修改cTest,但是骗不过VC编译后的代码。
...全文
285 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
alen_ghl 2005-09-13
  • 打赏
  • 举报
回复
学习
masterz 2005-09-13
  • 打赏
  • 举报
回复
内存保护的异常由硬件触发的,memory page有访问控制的标记,如果违反了会产生exception,所以你看不到指令
joymouse 2005-09-13
  • 打赏
  • 举报
回复
查阅了一些资料,明白了一些,我估计VC是用VirtualAlloc或者VirtualProtect之类的windows调用为应用程序的代码区、数据段等保留了不同的虚拟内存,用VirtualAlloc这些方式申请的内存是可以设置内存页的保护权限的。只是不知道这里面的更深一层的保护原理是什么。是否最终是靠CPU来实现还是操作系统实现。因为一个简单的mov指令就可以激活异常,不知道如何实现的。
goodname008 2005-09-12
  • 打赏
  • 举报
回复
看看变量的地址所在的内存页的属性就明白了。 :D
  • 打赏
  • 举报
回复
const char cTest = 'A';
char *pTest;

pTest = &cTest; //应该编译不过吧?常量的地址是不能赋给无约束的指针的
alloutoflove 2005-09-12
  • 打赏
  • 举报
回复
跟踪汇编语句应该能看出来两个编译器编译出来代码的不一样的.
皮皮鲁 2005-09-12
  • 打赏
  • 举报
回复
这跟VC的保护方式无关,只是不同的编译器将不同的变量或者常量放在不同的地方而已

VC编译器将字符常量放在只读数据区,页面的属性只读的,在程序中去修改当然会产生写保护异常,而你的程序没有捕捉这个异常,自然程序异常终止。如果你用WriteProcessMemory()函数来修改字符常量就不会有问题,因为这个函数里面会捕捉这个异常,然后将只读属性去掉再修改,当然最后它会将只读属性加回去。
const变量一个道理,VC将它放在只读属性的页面中去。

而BCB没有将他们所在的页面设为只读,执行期自然不会产生异常
oyljerry 2005-09-12
  • 打赏
  • 举报
回复
VC和CB对这个 的处理方式不同
huabihan 2005-09-12
  • 打赏
  • 举报
回复
存放的地方可能不一样.up
mymyal123 2005-09-12
  • 打赏
  • 举报
回复
up
masterz 2005-09-12
  • 打赏
  • 举报
回复
看看MSDN中Platform SDK: Memory Management
Memory Protection
Memory that belongs to a process is implicitly protected by its private virtual address space. In addition, Windows provides memory protection by using the virtual memory hardware. The implementation of this protection varies with the processor, for example, code pages in the address space of a process can be marked read-only and protected from modification by user-mode threads.
The following table identifies the memory-protection options that Windows provides, and you must specify one of the following values when allocating or protecting a page in memory.
PAGE_EXECUTE
0x10 Enables execute access to the committed region of pages. An attempt to read or write to the committed region results in an access violation.
This flag is not supported by CreateFileMapping.

PAGE_EXECUTE_READ
0x20 Enables execute and read access to the committed region of pages. An attempt to write to the committed region results in an access violation.
This flag is not supported by CreateFileMapping.

PAGE_EXECUTE_READWRITE
0x40 Enables execute, read, and write access to the committed region of pages.
This flag is not supported by CreateFileMapping.

PAGE_EXECUTE_WRITECOPY
0x80 Enables execute, read, and write access to the committed region of image file code pages. The pages are shared read-on-write and copy-on-write.
This flag is not supported by VirtualAlloc, VirtualAllocEx, or CreateFileMapping.

PAGE_NOACCESS
0x01 Disables all access to the committed region of pages. An attempt to read from, write to, or execute the committed region results in an access violation exception, called a general protection (GP) fault.
This flag is not supported by CreateFileMapping.

PAGE_READONLY
0x02 Enables read access to the committed region of pages. An attempt to write to the committed region results in an access violation. If the system differentiates between read-only access and execute access, an attempt to execute code in the committed region results in an access violation.
PAGE_READWRITE
0x04 Enables both read and write access to the committed region of pages.
PAGE_WRITECOPY
0x08 Gives copy-on-write protection to the committed region of pages.
This flag is not supported by VirtualAlloc or VirtualAllocEx.

Windows Me/98/95: This flag is not supported.
估计VC++把常量放在一段没有PAGE_READWRITE内存中。


16,551

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Creator Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧