指针运算和继承导致未定义的行为
Pointer Arithmetic and Inheritance result in undefined behauviour
当 运行 我的程序在第二次执行 cout<<Core32->name()
时终止。在研究了这个问题之后,我了解到在这种情况下指针运算会导致问题。我也可以通过用 Core32+04;
替换 Core32++;
来解决问题(真的不知道为什么会这样)。尽管如此,我的问题是为什么我能够调用方法 Core32->procfun()
而不是 Core32->name()
。我查找了对象切片,但它似乎并没有解决我的问题。
编辑:想知道为什么它只能调用 procfun() 而不能调用 name()。
这是一个旧考试的例子
#include <iostream>
#include<string>
using namespace std;
class Prozessor{
public:
virtual string name()=0;
};
class ARM : public Prozessor{
public:
virtual string name(){return "VAR";};
virtual int procbitw()=0;
string procfun(){return "VFP";};
};
class ARMv7:public ARM{
public:
int procbitw(){return 32;};
string procfun(){return "VFP";};
};
class ARMv8:public ARM{
public:
int procbitw(){return 64;};
string procfun(){return "VFP, NEON";};
};
int main()
{
const unsigned int n_cores=4;
ARM *HetQuadCore[n_cores]={new ARMv7, new ARMv7, new ARMv8, new ARMv8};
ARMv7* Core32=(ARMv7*)HetQuadCore[0];
for(int i =0;i<n_cores;i++)
{
cout<<Core32->procfun()<<endl;
cout<<Core32->name()<<endl;
cout<<"Bandwith is "<<HetQuadCore[i]->procbitw()<<endl;
Core32++;
}
return 0;
}
您可以调用 Core32->procfun
,因为它不是虚函数(因此不需要访问 vtable)并且不使用任何内部数据。
由于 this
参数无效,因此对内部数据的任何访问都可能会失败。
question is why I was able to call the Method Core32->procfun()
but not Core32->name()
因为行为未定义。
在这两种情况下都未定义。一种可能的行为是 "I was able to call the Method"。另一种可能的行为是 "my programm it terminates".
Also i was able to fix the problem by substituting Core32++; with Core32+04
一种可能的行为可能看起来像 "i was able to fix the problem",但仅仅因为它可能看起来如此,并不意味着未定义的行为已得到修复。
问题是 Core32
不是指向数组元素的指针,因此递增它不会产生有效对象。你可以这样做:
for(int i =0;i<n_cores;i++)
{
if (auto ptr7 = dynamic_cast<ARMv7*>(HetQuadCore[i]))
cout<<ptr7->procfun()<<endl;
else if (auto ptr8 = dynamic_cast<ARMv8*>(HetQuadCore[i]))
cout<<ptr8->procfun()<<endl;
cout<<HetQuadCore[i]->name()<<endl;
cout<<"Bandwith is "<<HetQuadCore[i]->procbitw()<<endl;
Core32++;
}
但是,将 procfun
虚拟化可能会更好。
你增加了错误的东西。
你有一个指针数组,对吧?而且你还有一个指针指向那个数组中的一个指针。
您正在递增对象指针之一,而不是数组指针。
Array Hypothetical Objects Your pointer
"array pointer" (scattered) "Core32"
┃
╔══════╗ «━━━━ aPtr ╔═══════╗ ┃
║ ptr1 ║━━━━━━━━━━━━━━━━━━━━━━»║ ARMv7 ║«━━━━━━━━━━━━━━┛
╠══════╣ ↓ ++aPtr ╚═══════╝
║ ptr2 ║━━━━━━━━━━━━━━━━━━━━━━━━┓ ╔═══════╗
╠══════╣ ↓ ++aPtr ┃ ╔═══════╗ ┏━━━»║ ARMv8 ║
║ ptr3 ║━━━━━━━━━━━━━━━━━━━━━━┓ ┗━»║ ARMv7 ║ ┃ ╚═══════╝
╠══════╣ ↓ ++aPtr ┃ ╚═══════╝ ┃
║ ptr4 ║━━━━━━━━━━━━━━━━━━━━━┓┗━━━━━━━━━━━━━━━┛ ╔═══════╗
╠══════╣ ↓ ++aPtr ┗━━━━━━━━━━━━━━━━━━»║ ARMv8 ║
║ … ║ ╚═══════╝
╙┄┄┄┄┄┄╜
因为这些对象 [可能] 分散,增加 Core32
只会让你胡说八道。这永远不能保证有效。只有当 new
调用为您提供内存中相邻的动态分配对象时,它才会起作用。
您应该只使用 i
来迭代数组,就像您已经在做的那样,或者使用一个指针 aPtr
来迭代数组的元素,然后再次取消引用以获得元素指向的对象。
当 运行 我的程序在第二次执行 cout<<Core32->name()
时终止。在研究了这个问题之后,我了解到在这种情况下指针运算会导致问题。我也可以通过用 Core32+04;
替换 Core32++;
来解决问题(真的不知道为什么会这样)。尽管如此,我的问题是为什么我能够调用方法 Core32->procfun()
而不是 Core32->name()
。我查找了对象切片,但它似乎并没有解决我的问题。
编辑:想知道为什么它只能调用 procfun() 而不能调用 name()。 这是一个旧考试的例子
#include <iostream>
#include<string>
using namespace std;
class Prozessor{
public:
virtual string name()=0;
};
class ARM : public Prozessor{
public:
virtual string name(){return "VAR";};
virtual int procbitw()=0;
string procfun(){return "VFP";};
};
class ARMv7:public ARM{
public:
int procbitw(){return 32;};
string procfun(){return "VFP";};
};
class ARMv8:public ARM{
public:
int procbitw(){return 64;};
string procfun(){return "VFP, NEON";};
};
int main()
{
const unsigned int n_cores=4;
ARM *HetQuadCore[n_cores]={new ARMv7, new ARMv7, new ARMv8, new ARMv8};
ARMv7* Core32=(ARMv7*)HetQuadCore[0];
for(int i =0;i<n_cores;i++)
{
cout<<Core32->procfun()<<endl;
cout<<Core32->name()<<endl;
cout<<"Bandwith is "<<HetQuadCore[i]->procbitw()<<endl;
Core32++;
}
return 0;
}
您可以调用 Core32->procfun
,因为它不是虚函数(因此不需要访问 vtable)并且不使用任何内部数据。
由于 this
参数无效,因此对内部数据的任何访问都可能会失败。
question is why I was able to call the Method
Core32->procfun()
but notCore32->name()
因为行为未定义。
在这两种情况下都未定义。一种可能的行为是 "I was able to call the Method"。另一种可能的行为是 "my programm it terminates".
Also i was able to fix the problem by substituting Core32++; with Core32+04
一种可能的行为可能看起来像 "i was able to fix the problem",但仅仅因为它可能看起来如此,并不意味着未定义的行为已得到修复。
问题是 Core32
不是指向数组元素的指针,因此递增它不会产生有效对象。你可以这样做:
for(int i =0;i<n_cores;i++)
{
if (auto ptr7 = dynamic_cast<ARMv7*>(HetQuadCore[i]))
cout<<ptr7->procfun()<<endl;
else if (auto ptr8 = dynamic_cast<ARMv8*>(HetQuadCore[i]))
cout<<ptr8->procfun()<<endl;
cout<<HetQuadCore[i]->name()<<endl;
cout<<"Bandwith is "<<HetQuadCore[i]->procbitw()<<endl;
Core32++;
}
但是,将 procfun
虚拟化可能会更好。
你增加了错误的东西。
你有一个指针数组,对吧?而且你还有一个指针指向那个数组中的一个指针。
您正在递增对象指针之一,而不是数组指针。
Array Hypothetical Objects Your pointer
"array pointer" (scattered) "Core32"
┃
╔══════╗ «━━━━ aPtr ╔═══════╗ ┃
║ ptr1 ║━━━━━━━━━━━━━━━━━━━━━━»║ ARMv7 ║«━━━━━━━━━━━━━━┛
╠══════╣ ↓ ++aPtr ╚═══════╝
║ ptr2 ║━━━━━━━━━━━━━━━━━━━━━━━━┓ ╔═══════╗
╠══════╣ ↓ ++aPtr ┃ ╔═══════╗ ┏━━━»║ ARMv8 ║
║ ptr3 ║━━━━━━━━━━━━━━━━━━━━━━┓ ┗━»║ ARMv7 ║ ┃ ╚═══════╝
╠══════╣ ↓ ++aPtr ┃ ╚═══════╝ ┃
║ ptr4 ║━━━━━━━━━━━━━━━━━━━━━┓┗━━━━━━━━━━━━━━━┛ ╔═══════╗
╠══════╣ ↓ ++aPtr ┗━━━━━━━━━━━━━━━━━━»║ ARMv8 ║
║ … ║ ╚═══════╝
╙┄┄┄┄┄┄╜
因为这些对象 [可能] 分散,增加 Core32
只会让你胡说八道。这永远不能保证有效。只有当 new
调用为您提供内存中相邻的动态分配对象时,它才会起作用。
您应该只使用 i
来迭代数组,就像您已经在做的那样,或者使用一个指针 aPtr
来迭代数组的元素,然后再次取消引用以获得元素指向的对象。