标题
C++中不要将 const 后的东东再强制转换后赋值!
clq
浏览(0) +
2007-01-24 14:05:35 发表
编辑
关键字:
微软的BUG,请来看看!
可能不是BUG,但是我觉得很奇怪,有谁能告诉我为什么?
#include "stdafx.h"
#include
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
const int a(9);
const int * p;
p=const_cast(&a);
cout << "a=" << a << " before modify" << endl;
cout << "*p=" << *p << " before modify" << endl;
cout << "address of a=" << &a << " before modify" << endl;
cout << "p=" << p << " before modify" << endl << endl;
*const_cast(&a)=111;
cout << "a=" << a << " before modify" << endl;
cout << "*p=" << *p << " before modify" << endl;
cout << "address of a=" << &a << " before modify" << endl;
cout << "p=" << p << " before modify" << endl;
return 0;
}
请注意,修改后,*p 和 a 打印出来的值竟然不一样,如果在*const_cast(&a)=111;出设置一个断点,你可以发现在此句前后,调试里a的值是不一样的。
求教!谢谢
再问,如何给一个const的常量赋值?可以吗?
loveghb(温柔的毒药) 于 2005-6-22 13:57:20
自己先顶一个。
vcmute(横秋) 于 2005-6-22 14:08:28
const int a=9;
结果相反,呵呵
vcmute(横秋) 于 2005-6-22 14:13:14
看错了,sorry
以前修改常字符串的时候也运到这个问题,感觉是优化的问题
vcmute(横秋) 于 2005-6-22 14:14:36
汇编的时候,直接push 9
00401482 mov ebx,esp
00401484 push 9
00401486 mov eax,esp
loveghb(温柔的毒药) 于 2005-6-22 14:18:31
*const_cast(&a)=111;
问题是如上的语句执行后,我在监视器里观察的值确实是变了,VC6和VC7都是如此。
但是实际cout出来的值却还是原来的那个。
晕了,到底能不能改呢?如何改?是不是微软的调试器有问题?
Robinhoodgood(Steven) 于 2005-6-22 14:26:27
编译的时候就已经用9 替换 a 了
既然a是常量,这样做也是合理的
KevinWon(Kevin) 于 2005-6-22 14:32:57
这种情况即使看反汇编也是没有头绪 MSDN里面有说的 这样的赋值将造成不可预料的结果 >V< 够奸的
loveghb(温柔的毒药) 于 2005-6-22 14:36:55
Robinhoodgood(Steven)
老大,没仔细看就别乱说,我用p指针去修改a的值了。管他用什么替换的,问题是我调试的时候在监视器确实看到a的值从9变成111了,但是cout出来的还是111
说话前摆脱仔细看下,谢谢
icansaymyabc(学习与进步) 于 2005-6-22 14:43:26
当然不是BUG。
在Windows NT下无论如何不可能给 const 变量赋值的。因为这种变量位于只读内存区。就像写保护的软盘一样,软件不可能对它有所改变。
而一个指向该只读内存的指针却不同。它所代表的变量有 COPY_ON_Write 属性。就是说,当你想写它的时候,如果内存是只读的,就把数据copy到另一个可写的内存里去,通过地址映射,面向用户的地址却不变。
当然,这种机制只在WINdows下起作用。如果你那段代码运行在DOS下,就会输出你期望的结果,因为DOS没有内存保护机制。
在windows下你非要变态得一定要把一个变量定义成const又要去改它的值的话,也不是没办法。你必须改变那个变量所在的内存的那一页的属性使得它可读写,该掉该值后,恢复其只读属性。
loveghb(温柔的毒药) 于 2005-6-22 14:48:15
学习了。结帖
he_sl(he_sl) 于 2005-6-22 15:07:56
——》当你想写它的时候,如果内存是只读的,就把数据copy到另一个可写的内存里去
有没有办法看到它写到哪里去了?
askppp(菜鸟) 于 2005-6-22 17:00:03
同意icansaymyabc的观点,windows内存都是有权限的,只读,可写,可执行
不过只读区域是可以修改成为可写的
用
VirtualProtectEx
--------------------------------------------------
在
http://blog.csdn.net/haoel/archive/2006/11/19/1395358.aspx
也提到不要将 const 后的东东再强制转换后赋值
clq
说实话我真没想到过会是这种情况,我经常将 const char * 强制转换为 char *,然后再使用,因为很多C语言的参数类型是很少写成const 形式的,一般是直接写成 char *,而C++的一般会加const,当要同时使用它们时就只能是强制转换.当然了实际上这时的char *其实是作为常量使用的.我都已经习已为常了,还以为是C++在语法上的严格而已没想到会导致内存存储位置不同而导致内容不同.
不过从现象来看应该是初始为const的才会写到只读区,如果是char *转换为const char *,再转换为char *应该没问题.不过,以后还是小心点的好.
另外"陈皓专栏"http://blog.csdn.net/haoel/archive/2007/01/23/1491219.aspx中还说了,有些std::string实现会使用Copy-On-Write技术,就是说当写下 str2=str1 时它们的内存还有可能是相同的,这在多线程环境下会出问题的(似乎delphi的string也是有这个问题的),所以以后要用std::string在多线程中传递值的话还是自己赋值吧,别把string作为参数直接传递过去.我一直因为std::string的问题想重写一个string自己用算了,不过想想还是算了(代码还有别人要用的),用的时候注意一点吧.
NEWBT官方QQ群1: 276678893
可求档连环画,漫画;询问文本处理大师等软件使用技巧;求档softhub软件下载及使用技巧.
但不可"开车",严禁国家敏感话题,不可求档涉及版权的文档软件.
验证问题说明申请入群原因即可.