在Linux上使用g ++编译时,此代码工作正常,但是当我尝试在VS 2015(调试和发布(中执行它们时,我收到运行时错误。怎么了?
#include "stdafx.h"
#include <string.h>
#include <iostream>
using namespace std;
struct Stru1
{
int mem;
};
struct Stru2 : public Stru1
{
char szMem1[256];
int dwMem2;
int dwMem3;
};
static void clFun(Stru1* s) {
Stru2* s2 = (Stru2*)s;
cout << s2->szMem1 << endl;//blahblah
cout << s2->dwMem2 << endl;//runtime error
}
class Temp {
public:
void callDispatch() {
simRecv->mem = 2;
Stru2* sro = (Stru2*)simRecv;
strcpy(sro->szMem1, "blahblah");
sro->dwMem2 = 11;
sro->dwMem3 = 77;
//cout << sro->szMem1 << endl;//blahblah
//cout << sro->dwMem2 << endl;//runtime error when uncommented
clFun(simRecv);
}
~Temp() { delete simRecv; }
Stru1* simRecv = new Stru1;
};
int main()
{
Temp tmp;
tmp.callDispatch();
return 0;
}
错误: 控制台应用程序 1.exe 中的0x0000000077A0F23C (ntdll.dll( 引发异常: 0xC0000005:访问冲突读取位置0x00000FB00188C508。
Stru2* sro = (Stru2*)simRecv;
simRecv
是Stru1
,因此您在此行中对Stru2
的不安全投射无效。
在这一行中,您创建此Stru1
,
Stru1* simRecv = new Stru1;
这里 Stru1 被分配了创建小于Stru2
的Stru1
所需的内存。
通过做:
Stru2* sro = (Stru2*)simRecv;
你只是说:我有这个"东西",把它当作Stru2
.但是没有在任何地方创建new Stru2
,所以对象就不存在了。
基本上和说
我有一堵大墙,但我会把它当作房子,并期待里面有一扇门。
它可能在不同的平台上工作的原因可能是由于平台的内存分配不同。
至于类比:你可能已经到了墙的尽头,因此不会伤到你的头,但你不在房子里,你不会把钱包留在那里。
例如,此行最终将指向某处:
sro->dwMem3 = 77;
问题是:这是否在有效的程序空间内?如果是,则不会发生错误,但这并不意味着它是好的。您可能正在其他地方更改变量,从而导致不可预测的结果。
举个例子:
平台 1:
| Stru1 | some variable | some other variable |
| mem | 0 | 11 |
| | | ((Stru2*) simRecv)->dwMem2 |
//no errors, but strange side effects
平台2:
| Stru1 | some variable | some other program space |
| mem | 0 | ERROR: ACCES VIOLATION |
| | | ((Stru2*) simRecv)->dwMem2 |
//0xC0000005
如果您首先分配一个Stru2
(通过实际创建它(,一切都会很好:
Stru1* simRecv = (Stru1*) new Stru2;
话虽如此;这些演员被认为是不安全的(现在很明显的原因(。 另一种方法是使用,例如static_cast
.它将确保您在尝试执行"非法"操作时会遇到构建错误。
http://www.cplusplus.com/doc/tutorial/typecasting/
关于 cPlusPlus 的附加说明请参阅: cplusplus.com 有什么问题?