URN Logo
UNIX Resources » Linux » China Linux Forum » C/C++编程版 » 19 » 关于虚基类的强制转换所引发的crash.
announcement 声明: 本页内容为中国Linux论坛的内容镜像,文章的版权以及其他所有的相关权利属于中国Linux论坛和相应文章的作者,如果转载,请注明文章来源及相关版权信息。
Resources
China Linux Forum(finished)
Linux Forum(finished)
FreeBSD China(finished)
linuxforum.net
  业界新闻与评论
  自由软件杂谈
  IT 人生
  Linux软件快递
  翻译作坊
  Linux图书与评论
  GNU Emacs/XEmacs
  Linux 中文环境和中文化
  Linux桌面与办公软件
  Linux 多媒体与娱乐版
  自由之窗Mozilla
  笔记本电脑上的Linux
  Gentoo
  Debian 一族
  网络管理技术
  Linux 安装与入门
  WEB服务器和FTP服务器
  域名服务器和邮件服务器
  Linux防火墙和代理服务器应用
  文件及打印服务器
  技术培训与认证
  Linux内核技术
  Linux 嵌入技术
  Linux设备驱动程序
  Linux 集群技术
  LINUX平台数据库
  系统和网络安全
  CPU 与 编译器
  系统计算研究所专栏
  Linux下的GUI软件开发
  C/C++编程版
  PHP 技 术
  Java&jsp技术
  Shell编程技术
  Perl 编 程
  Python 编 程
  XML/Web Service 技术
  永远的Unix
  FreeBSD世界
   
关于虚基类的强制转换所引发的crash.
关于虚基类的强制转换所引发的crash. - ganxj [2006-02-21 19:02 | 891 byte(s)]
 
Re: 关于虚基类的强制转换所引发的crash. - ganxj [2006-03-05 17:14 | 1,239 byte(s)]
 
 
 
 
 
 
 
 
 
 
 
Subject: 关于虚基类的强制转换所引发的crash.
Author: ganxj    Posted: 2006-02-21 19:02    Length: 891 byte(s)
[Original] [Print] [Top]
Hi, 我碰到一个crash如下:

class A{
...
}

class B{ //vitual class
...
virtual fun1() = 0;
}

class C1 : public A,public B{
...
fun1(){...};
}

class C2 : public A,public B{

fun1(){...};
}

I pass the C1 object point "mypointer" to a function as void* then call fun1() it crash
extern "C"{
...
function(void * mypointer)
{
((B*)mypointer)->fun1();
}
}

but if I change
((B*)mypointer)->fun1();
to
((C1*)mypointer)->fun1();
it would be OK

Thanks for suggestion to avoid the crash
gan

[Original] [Print] [Top]
Subject: Re: 关于虚基类的强制转换所引发的crash.
Author: cjhsh    Posted: 2006-02-21 19:48    Length: 3 byte(s)
[Original] [Print] [Top]
...
[Original] [Print] [Top]
Subject: Re: 关于虚基类的强制转换所引发的crash.
Author: ganxj    Posted: 2006-02-21 21:05    Length: 35 byte(s)
[Original] [Print] [Top]
我觉得有道理但是改完仍是crash. 奇怪
[Original] [Print] [Top]
Subject: Re: 关于虚基类的强制转换所引发的crash.
Author: drangon_zhou    Posted: 2006-02-21 21:12    Length: 129 byte(s)
[Original] [Print] [Top]
不能强制类型转换吧,考虑使用dynamic_cast,如果要支持RTTI,
指向同一个对象的不同类型的pointer的位置的不一样的。
----
岂有豪情似旧时,花开花落两由之。
[Original] [Print] [Top]
Subject: Re: 关于虚基类的强制转换所引发的crash.
Author: ganxj    Posted: 2006-02-22 12:39    Length: 629 byte(s)
[Original] [Print] [Top]
我试了一下

class A{
...
}

class B{ //vitual class
...
virtual fun1() {};
}

class C1 : public A,public B{
...
fun1(){...};
}

class C2 : public A,public B{

fun1(){...};
}



C1* g = new C1();
void * x = g;

B* j= dynamic_cast <B*>((B*)x);
j->fun1();

仍然crash,是否在void * x = g;信息就丢了?dynamic_cast也找不到最派生类的指针了。
[Original] [Print] [Top]
Subject: Re: 关于虚基类的强制转换所引发的crash.
Author: cjhsh    Posted: 2006-02-22 13:54    Length: 387 byte(s)
[Original] [Print] [Top]
今天翻了翻书看虚函数的用法
发现偶昨天的回答是错地
如果想通过派生类调用基类的函数要加上作用域



C1* g = new C1();
void * x = g;

B* j= dynamic_cast <B*>((B*)x);
j->fun1();

改成

j->B::fun1();就可调用基类的fun1

[Original] [Print] [Top]
Subject: Re: 关于虚基类的强制转换所引发的crash.
Author: ganxj    Posted: 2006-02-22 15:10    Length: 20 byte(s)
[Original] [Print] [Top]
的确如此,非常感谢!
[Original] [Print] [Top]
Subject: Re: 关于虚基类的强制转换所引发的crash.
Author: ddd    Posted: 2006-02-22 20:11    Length: 57 byte(s)
[Original] [Print] [Top]
代码不贴完整谁知道怎么回事
99%是其他代码的问题。
----
I solemnly swear that I am up to no good
[Original] [Print] [Top]
Subject: Re: 关于虚基类的强制转换所引发的crash.
Author: acguy    Posted: 2006-02-23 12:36    Length: 839 byte(s)
[Original] [Print] [Top]


#include <iostream>
using namespace std;
做了个测试:

class A {
};

class B {
public:
virtual void fun();
};

class C : public A, public B {
public:
void fun();
};

void B::fun(){
cout<<"B function"<<endl;
}

void C::fun(){
cout<<"C function"<<endl;
}

int main(int argv, char *args[])
{
C *cp = new C();
void * vp = cp;
((B*)vp)->fun();
return 0;
}

结果输出 “C function",完全正常。
[Original] [Print] [Top]
Subject: Re: 关于虚基类的强制转换所引发的crash.
Author: ganxj    Posted: 2006-03-05 17:14    Length: 1,239 byte(s)
[Original] [Print] [Top]
网上问了一圈,觉得有一个解释有道理,贴在这里,如果谁碰到同样现象事供参考:
The problem is in wrong pointer conversion: C1* -> void* -> B*.
Conversion to/from void* assumes that both pointers refer to same
address.
But B is a second base of C1, and its subobject is shifted.
Thus, doing C1* -> void* -> B* you get an invalid pointer (of type B*
that refers to A subobject, not to B).
Dereferencing it leads to UB.
The program tries to read vfptr and get some junk value. And then
fails:
- dereferencing wrong vfptr and trying to read vtbl
- reading wrong address of fun1 and trying to jump there
- executing wrong instructions
and so on, and so on...

What to do:
As far as you know that your function(void*) accepts B*, you have to
pass B* there:
function( static_cast<B*>(ptrC1) );

Using static_cast<B*>(ptrC1) instead of C-style (B*)ptrC1 will protect
you from mistakes. If ptrC1 is not of type derived from B, the compiler
indicate an error.

[Original] [Print] [Top]
Subject: Re: 关于虚基类的强制转换所引发的crash.
Author: ddd    Posted: 2006-03-05 19:36    Length: 243 byte(s)
[Original] [Print] [Top]
这个外国人说对一半。
A中如果没有虚函数,那么不会发生shift事件。
所以这个情况出现的必要条件是A有虚函数。
static_cast<B*>(ptr)如果这个ptr类型是void*,并且是从C*转换过来的,那么这个表达式的结果和(B*)一样。
----
I solemnly swear that I am up to no good
[Original] [Print] [Top]
Subject: Re: 关于虚基类的强制转换所引发的crash.
Author: ganxj    Posted: 2006-03-07 21:30    Length: 8 byte(s)
[Original] [Print] [Top]
谢谢指点
[Original] [Print] [Top]
« Previous thread
请教一个汉字库的问题
C/C++编程版
19
Next thread »
建好了ppp链路,想编一个文件收发的程序,请各位指点一下
     

Copyright © 2007 UNIX Resources Network, All Rights Reserved.      About URN | Privacy & Legal | Help | Contact us
备案序号: 京ICP备05006143    webmaster: webmaster@unixresources.net
This page created on 2008-07-17 03:52:19, cost 0.061568975448608 ms.