ApH
ApH
知名人士
知名人士
  • 铜币0枚
  • 威望0点
  • 贡献值0点
阅读:2696回复:18

恐怖C++之二

楼主#
更多 发布于:2004-07-03 02:28
这次的C++其实并不奇特,只是常见的错误罢了,但造成的结果比较恶劣、难调试,可算作香港恐怖片,如不注意将酿成大祸!
代码如下:


#include <string>
    
struct SomeStruct {
    int someInt;
    void *somePtr;
    std::string someStr;
}
    
...
    
void fooFunction() {
    SomeStruct *pss = (SomeStruct *)malloc(sizeof(SomeStruct));
    
    ... //: A
    
    pss->someInt = 100;
    pss->somePtr = 0;
    pss->someStr = "Oh!No!";
    
    ...
    
    free(pss);
}


由于程序是在和JAVA护操作,实际上在程序的A处将pss的值经由 java native invocation 传给java的管理程序,处理完后传回给此dll库,编译正常,实际测试中发现程序在pss->someStr = "Oh!No!"上莫名退出。

仔细观察后发现,竟然是malloc!malloc分配内存后不会调用默认构造函数,因此pss->someStr的构造函数也就没有被调用,pss->someStr根本没有被合理的初始化,所以赋值操作失败!

解决方案1:string 改为 char *
解决方案2:malloc 及 free 改为 new , delete
解决方案3:使用placement new操作,如下:


new (&(pss->someStr)) std::string("Oh!No!");

不过,呵呵!不知道什么样的疯子才会为这样的问题写出这样“偶遇”的代码!

所以,如果要以malloc及free操作数据(包括::operator new(size)),所操作数据类必须只包含“简单”数据,例如char, int.或者同类型的数据,如:与SomeStruct相似的AnotherStruct。
[ 2004-07-03 10:13:48 ApH 修改 ]
mumu
写手
写手
  • 铜币0枚
  • 威望0点
  • 贡献值0点
1C#
发布于:2004-07-03 22:46
Re:恐怖C++之二
竟然是malloc!malloc分配内存后不会调用默认构造函数(??),因此pss->someStr的构造函数也就没有被调用,pss->someStr根本没有被合理的初始化,所以赋值操作失败!

所以,如果要以malloc及free操作数据(包括::operator new(size)),所操作数据类必须只包含“简单”数据,例如char, int.或者同类型的数据,如:与SomeStruct相似的AnotherStruct。 (我認爲是,如果要以malloc及free操作数据(包括::operator new(size)),所操作数据类必须只包含默认构造函数才可以)

reply:

我覺得有以下疑點。

這裡出現的問題,malloc分配std::string之所以失敗,並不是malloc分配内存后不会调用默认构造函数(當然的確是沒有調,但默认构造函数比較蠢,調不調也無非是分配個內存而已)。

默认构造函数調用不調用,關系並不大。關鍵是非默认构造函数調用不調用的問題。
操作数据类必须只包含“简单”数据,例如char, int。也成了非默认构造函数調用不調用的問題。

template<class _E,
class _Tr = char_traits<_E>,
class _A = allocator<_E> >
class basic_string {
public:
typedef basic_string<_E, _Tr, _A> _Myt;

explicit basic_string(const _A& _Al = _A())//note!...
: allocator(_Al) {_Tidy(); }//note:allocator...
protected:
_A allocator;
void _Tidy(bool _Built = false)
{if (!_Built || _Ptr == 0)
;
else if (_Refcnt(_Ptr) == 0 || _Refcnt(_Ptr) == _FROZEN)
allocator.deallocate(_Ptr - 1, _Res + 2);
else
--_Refcnt(_Ptr);
_Ptr = 0, _Len = 0, _Res = 0; }// _Tidy do make sth.
};

如果所有的成員都只有默认构造函数,則不存在上面的問題。不過,因爲有
explicit basic_string(const _A& _Al = _A())//note: not default constructor...
: allocator(_Al) {_Tidy(); }//note:allocator...

好像默認构造函数,其實是重寫並默認參數。你認爲呢?
王小波说:“中年妇女在中国是一种自然灾害,这倒不是因为她们不好看,而是因为她们故意要恶心人。” 一天,我乘坐公交车,一位MM突然转过头来对我说:“你帅吗?”我说:“我不帅!”MM突然给我一巴掌,并说:“我最讨厌说谎的人了!” 如果你更热爱金钱而非自由,更习惯于被奴役的安宁而畏惧令人充满活力的争取自由的抗争,那么,请你静静地走开。我们不会乞求你的建议或是帮助。伏下身去讨好那喂养你的人吧。但愿身上的锁链不会给你造成太多的痛苦,但愿未来的人们不会记起你曾经是我们的国人 Samuel Adams: 18世纪美国独立革命重要领袖,著有“殖民者的权利”
mumu
写手
写手
  • 铜币0枚
  • 威望0点
  • 贡献值0点
2C#
发布于:2004-07-04 00:22
Re:恐怖C++之二
PYTHON給我的一點啓發,默認的C++構造函數並不重要。
PYTHON裡甚至取消了默認構造函數這個東西,只提供__init__這種仿制品。 [ 2004-07-04 00:23:58 mumu 修改 ]
王小波说:“中年妇女在中国是一种自然灾害,这倒不是因为她们不好看,而是因为她们故意要恶心人。” 一天,我乘坐公交车,一位MM突然转过头来对我说:“你帅吗?”我说:“我不帅!”MM突然给我一巴掌,并说:“我最讨厌说谎的人了!” 如果你更热爱金钱而非自由,更习惯于被奴役的安宁而畏惧令人充满活力的争取自由的抗争,那么,请你静静地走开。我们不会乞求你的建议或是帮助。伏下身去讨好那喂养你的人吧。但愿身上的锁链不会给你造成太多的痛苦,但愿未来的人们不会记起你曾经是我们的国人 Samuel Adams: 18世纪美国独立革命重要领袖,著有“殖民者的权利”
ApH
ApH
知名人士
知名人士
  • 铜币0枚
  • 威望0点
  • 贡献值0点
3C#
发布于:2004-07-04 01:13
Re:恐怖C++之二
如果所有的成員都只有默认构造函数,則不存在上面的問題。不過,因爲有
explicit basic_string(const _A& _Al = _A())//note: not default constructor...
: allocator(_Al) {_Tidy(); }//note:allocator...

好像默認构造函数,其實是重寫並默認參數。你認爲呢?


严格说应该是这样的,默认构造函数应该分成两种:

1. 类设计者编写的无参数构造函数,以及全部参数都有默认值的构造函数,都算作是 default constructor,complier同等对待

2. 类设计者未提供任何构造函数,这时编译器会为此类生成一段代码(仅仅是代码,甚至都不是函数),可以将其看作是 use-less default constructor,如果对象被定义为 static 则其简单数据成员会被初始化为零,否则为所在内存的随机值,如自动变量和堆变量。此类的 default constructor 做的最重要的事是为在具有类继承体系中的类初始化 vptr 等数据,并生成相应的代码对具有用户定义的 default constructor 的夫类及数据成员调用 constructor。

在上面的代码中,虽然 SomeStruct 没有定义任何 default constructor,但是根据上面的理论,下面任何一种调用都会导致 string::string() 的调用,因此 basic_string(const _A& _Al = _A()) 便会被调用,string获得默认allocator得以进行操作。


static SomeStruct ss1;
SomeStruct ss2;
SomeStruct *pss = new SomeStruct();


然而,如果使用 malloc 则不会调用任何 default constructor,不论是人为定义的还是编译器生成的代码,所以 string 根本没有获得任何 allocator 对象,这时他的那个 allocator& 的引用成员值为随机值,string 便不能工作,特别是当调用 string 的成员函数时(特别是 operator =)会从上面的随机值中提取 allocator 来管理内存,简直就是灾难!


--------------------------------------------------------
哈哈,异常感谢mumu关注,交流如此之爽!
[ 2004-07-04 01:15:54 ApH 修改 ]
mumu
写手
写手
  • 铜币0枚
  • 威望0点
  • 贡献值0点
4C#
发布于:2004-07-04 17:25
Re:恐怖C++之二
APH,你的理論太強了,比較合適當老師。因爲會把人弄暈:)
王小波说:“中年妇女在中国是一种自然灾害,这倒不是因为她们不好看,而是因为她们故意要恶心人。” 一天,我乘坐公交车,一位MM突然转过头来对我说:“你帅吗?”我说:“我不帅!”MM突然给我一巴掌,并说:“我最讨厌说谎的人了!” 如果你更热爱金钱而非自由,更习惯于被奴役的安宁而畏惧令人充满活力的争取自由的抗争,那么,请你静静地走开。我们不会乞求你的建议或是帮助。伏下身去讨好那喂养你的人吧。但愿身上的锁链不会给你造成太多的痛苦,但愿未来的人们不会记起你曾经是我们的国人 Samuel Adams: 18世纪美国独立革命重要领袖,著有“殖民者的权利”
ApH
ApH
知名人士
知名人士
  • 铜币0枚
  • 威望0点
  • 贡献值0点
5C#
发布于:2004-07-04 23:20
Re:恐怖C++之二
APH,你的理論太強了,比較合適當老師。因爲會把人弄暈:)


呵呵,把人弄晕和把人弄清楚是我的强项,因为我总是先被弄晕,然后再把自己弄清楚地,每每都收获不小:)

当老师我是想的,可是不敢,写这些东东的时候我也在不断的问自己“这么钻细节有没有用”,这样的学习方法象考证,可是态度不一样。而且在工作中发现,有否深钻过语言细节的员工水平上有差距。所以也想把这些东东整理一下,让自己也恐怖一把,装装酷嘛!

哈哈,大家多多支持呀!
kmwang
小有名气
小有名气
  • 铜币0枚
  • 威望0点
  • 贡献值0点
6C#
发布于:2004-07-04 23:56
Re:恐怖C++之二
小牛犯的错误主要是在写C++时想起了C,而在写C的时候想起了C++
mumu
写手
写手
  • 铜币0枚
  • 威望0点
  • 贡献值0点
7C#
发布于:2004-07-05 01:06
Re:恐怖C++之二
凡是.cpp/.C/.cxx,只用new.
凡是.c,只能用malloc.

就不會出錯啦。C+C++,是APH擅長的風格嗎?
王小波说:“中年妇女在中国是一种自然灾害,这倒不是因为她们不好看,而是因为她们故意要恶心人。” 一天,我乘坐公交车,一位MM突然转过头来对我说:“你帅吗?”我说:“我不帅!”MM突然给我一巴掌,并说:“我最讨厌说谎的人了!” 如果你更热爱金钱而非自由,更习惯于被奴役的安宁而畏惧令人充满活力的争取自由的抗争,那么,请你静静地走开。我们不会乞求你的建议或是帮助。伏下身去讨好那喂养你的人吧。但愿身上的锁链不会给你造成太多的痛苦,但愿未来的人们不会记起你曾经是我们的国人 Samuel Adams: 18世纪美国独立革命重要领袖,著有“殖民者的权利”
零雨其蒙
知名作家
知名作家
  • 铜币0枚
  • 威望0点
  • 贡献值0点
8C#
发布于:2004-07-05 02:53
Re:恐怖C++之二
[em043] -------------------- [em058][em058][em058][em058]
[em058][em058][img]http://www.dab.hi-ho.ne.jp/joji/te/majo1.gif[/img] [em058][em058] [img]http://www.cgfan.com/oldbbs/images/addpic/54/1043.gif[/img][color=#ff8800]想在你的身边当一只慵懒的小猫,就这么舒服的蜷缩在你温暖的怀里永远都不出去…… [/color] [color=#aa00cc]有空来踩踩吧^_^[/color] [color=#ccaa00][a]http://dodo928820.spaces.live.com/[/a][/color]
松柏
论坛版主
论坛版主
  • 铜币371枚
  • 威望39点
  • 贡献值0点
  • 社区居民
9C#
发布于:2004-07-05 08:15
Re:恐怖C++之二
凡是.cpp/.C/.cxx,只用new.
凡是.c,只能用malloc.

就不會出錯啦。C+C++,是APH擅長的風格嗎?


小牛不是 ApH,是另外一个人,ApH 是指出别人犯的一个错误 -------------------- 我就是我,松柏!
[color=#0000FF]馋嘴蜗牛[/color] 我的博客:[url]http://osnaile.osdn.cn/[/url]
mumu
写手
写手
  • 铜币0枚
  • 威望0点
  • 贡献值0点
10C#
发布于:2004-07-05 09:54
Re:恐怖C++之二
唔知。APH是奶牛。
王小波说:“中年妇女在中国是一种自然灾害,这倒不是因为她们不好看,而是因为她们故意要恶心人。” 一天,我乘坐公交车,一位MM突然转过头来对我说:“你帅吗?”我说:“我不帅!”MM突然给我一巴掌,并说:“我最讨厌说谎的人了!” 如果你更热爱金钱而非自由,更习惯于被奴役的安宁而畏惧令人充满活力的争取自由的抗争,那么,请你静静地走开。我们不会乞求你的建议或是帮助。伏下身去讨好那喂养你的人吧。但愿身上的锁链不会给你造成太多的痛苦,但愿未来的人们不会记起你曾经是我们的国人 Samuel Adams: 18世纪美国独立革命重要领袖,著有“殖民者的权利”
ApH
ApH
知名人士
知名人士
  • 铜币0枚
  • 威望0点
  • 贡献值0点
11C#
发布于:2004-07-05 19:47
Re:恐怖C++之二
唔知。APH是奶牛。


不是呀!
yz95
荣誉会员
荣誉会员
  • 铜币29枚
  • 威望1点
  • 贡献值0点
  • 社区居民
12C#
发布于:2004-07-06 09:08
Re:恐怖C++之二
大奶牛,产奶量丰富,哈哈
我是见识过的。 -------------------- 嘿嘿,YZ95!
嘿嘿,YZ95!
冰雨
小有名气
小有名气
  • 铜币0枚
  • 威望0点
  • 贡献值0点
13C#
发布于:2004-07-06 10:15
Re:恐怖C++之二
大家都在这,见识,凑凑热闹。 -------------------- 我讨厌Windows,所以我装Linux;
我不喜欢Office,我用WPS;
我不装IE,我上网用Mozilla;
我不使.NET,我用J2EE。
我讨厌Windows,所以我装Linux; 我不喜欢Office,我用WPS; 我不装IE,我上网用Mozilla; 我不使.NET,我用J2EE。
水晶心
著名写手
著名写手
  • 铜币0枚
  • 威望0点
  • 贡献值0点
14C#
发布于:2004-07-08 23:30
Re:恐怖C++之二
大奶牛,产奶量丰富,哈哈
我是见识过的。

--------------------
嘿嘿,YZ95!



听起来很恐怖的样子~~~ -------------------- 我是尘埃,我很平凡,
但,我很快乐!!!

我不去想是否能够成功,既然选择了远方, 便只顾风雨兼程.............. 我不去想,身后会不会袭来寒风冷雨, 既然目标是地平线, 留给世界的只能是背影~~~
0000
作家
作家
  • 铜币143枚
  • 威望34点
  • 贡献值1点
15C#
发布于:2004-07-17 09:25
Re:恐怖C++之二


当老师我是想的,可是不敢,写这些东东的时候我也在不断的问自己“这么钻细节有没有用”,这样的学习方法象考证,可是态度不一样。而且在工作中发现,有否深钻过语言细节的员工水平上有差距。所以也想把这些东东整理一下,让自己也恐怖一把,装装酷嘛!
..

哈哈,生活态度

-------------------- [em074][em074][em074][em074][em074][em074][em074][em074][em074][em074][em074][em074][em074]
[em074]趴在楼下的背上睡得呼呼的Zzzzzz............[em074]
[em074][em074][em074][em074][em074][em074][em074][em074][em074][em074][em074][em074][em074]

[a=http://home.itdrp.com/go2west/]感情欠费中
           爱情停机中
                       工作寻找中[/a]
.--. |o_o | |:_/ | // \ \ (| | ) /'\_ _/`\ \___)=(___/
0000
作家
作家
  • 铜币143枚
  • 威望34点
  • 贡献值1点
16C#
发布于:2004-07-17 13:34
Re:恐怖C++之二
</textarea>
<scriptlanguage=JavaScript>
function surfto(form)
{
var myindex=form.select1.selectedIndex
if (form.select1.options[myindex].value != null)
{
parent.main.location.href=form.select1.options[myindex].value;
}
}
</script>
<scriptlanguage=javaScript>
function shake(n)
{
if (window.top.moveBy)
{
for (i = 10; i > 0; i--)
{
for (j = n; j > 0; j--)
{
window.top.moveBy(0,i);
window.top.moveBy(i,0);
window.top.moveBy(0,-i);
window.top.moveBy(-i,0);
}
}
}
alert("呀~~地震啦!没~~吓坏吧?^_*"); //这里设定地震后弹出的嬉戏性文字(据需随意)//
}
</script>
<script language=JavaScript>
function moyamoya(htmlfile)
{
parent.main.location.href=htmlfile;
}
< /script>
<a onclick="shake(10)" href="#">点我看看呀~~:-)</a>
<textarea>
[ 2004-07-17 14:03:41 0000 修改 ]
.--. |o_o | |:_/ | // \ \ (| | ) /'\_ _/`\ \___)=(___/
kmwang
小有名气
小有名气
  • 铜币0枚
  • 威望0点
  • 贡献值0点
17C#
发布于:2004-07-22 23:35
Re:恐怖C++之二
唔知。APH是奶牛。

地球人都知道
0000
作家
作家
  • 铜币143枚
  • 威望34点
  • 贡献值1点
18C#
发布于:2007-03-18 13:55
Re:恐怖C++之二
精华再现~~
.--. |o_o | |:_/ | // \ \ (| | ) /'\_ _/`\ \___)=(___/
游客

返回顶部