在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;
}
错误: ConsoleApplication1.exe中0x0000000077A0F23C(ntdll.dll)抛出异常:0xC0000005:访问冲突读取位置0x00000FB00188C508。
答案 0 :(得分:2)
Stru2* sro = (Stru2*)simRecv;
simRecv
是Stru1
,因此您对Stru2
的不安全转换在此行中无效。
在此行中,您可以创建此Stru1
,
Stru1* simRecv = new Stru1;
此处为Stru1分配了创建Stru1
所需的内存,该内存小于Stru2
。
通过做:
Stru2* sro = (Stru2*)simRecv;
你只是说:我有这个“东西”并将其视为Stru2
。但是在任何地方都没有创建new Stru2
因此对象就不存在了。
它与说
基本相同我有一堵大墙,但我会把它当作一所房子,并期待它有一扇门。
可能在不同平台上工作的原因可能是由于平台的内存分配不同。
至于类比:你可能到达墙的尽头,因此不会伤到你的头,但你不在屋内,你不会把你的钱包放在那里。
例如,这一行最终会指向某个地方:
sro->dwMem3 = 77;
问题是:这是否在有效的程序空间内?如果是,则不会发生错误,但这并不意味着它是好的。你可能正在改变一个变量,在其他地方,导致不可预测的结果。
一个例子:
PLATFORM1:
| Stru1 | some variable | some other variable |
| mem | 0 | 11 |
| | | ((Stru2*) simRecv)->dwMem2 |
//no errors, but strange side effects
PLATFORM2:
| 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的其他说明请参阅:What's wrong with cplusplus.com?