【发布时间】:2014-01-22 13:30:14
【问题描述】:
例子
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <iomanip>
struct father
{
int variable;
father(){variable=0xEEEEEEEE;};
virtual void sing(){printf("trollolo,%x\n",variable);}
~father(){};
};
struct son:father
{
son(){variable=0xDDDDDDDD;};
virtual void sing(){printf("trillili,%x\n",variable);}
~son(){};
};
int main()
{
father * ifather=new(father);
son * ison=new(son);
father uncle;
father * iteachers;
*((long long*)&uncle)=0xDEAF;
iteachers=(father*)malloc(20*sizeof(father));
//ineffective assignments
iteachers[0]=*ifather;
uncle=*ifather;
ifather->sing();//called to prevent optimization
ison->sing();//only to prevent optimization
std::cout.setf(std::ios::hex);
std::cout<<"father:"<<*((long long*)ifather)<<","<<std::endl;
std::cout<<"teacher0:"<<*((long long*)&(iteachers[0]))<<","<<std::endl;
std::cout<<"uncle:"<<*((long long*)&uncle)<<","<<std::endl;
std::cout<<"(son:"<<*((long long*)ison)<<"),"<<std::endl;
// uncle.sing();//would crash
}
使用 gcc 编译时,teacher[0] 的 vtable 指针为零。
uncle 的 vtable 指针也保持其原始值,而不是被覆盖。
我的问题:为什么会这样?
有干净的解决方法吗?我可以使用uncle._vptr=ifather->_vptr 并且仍然可以携带吗?复制对象的 ORDINARY 例程是什么?我什至应该提交错误吗?
注意:它应该复制整个对象平台无关,因为无论对象类型如何识别,它都应该始终在对象的数据块内!
文章
Why does my C++ object loses its VPTr
没有帮助我,那一定有不同的原因。
【问题讨论】:
-
只需使用复制构造函数,停止黑客攻击。请使用
std::vector和new而不是malloc。如果要编写 C 代码,使用 C++ 有什么意义? -
*((long long*)&uncle)=0xDEAF;应该做什么?你想完成什么? -
*((long long*)&uncle)=0xDEAF;应该只是证明没有任何东西被写入 vptr 位置 - 您留在那里的任何 trash 都会被保留。编辑:这意味着复制例程不会从指针指向的数据块的开头开始 - 非常意外! -
您想知道为什么未定义的程序“行为不端”吗?
-
如果 vtable 指针被复制,我会感到非常惊讶,因为它们无法更改(这将需要更改对象的动态类型,这是不可能的)。