在 VS2015 中访问类成员时出现运行时错误,但在 Linux 上没有
Posted
技术标签:
【中文标题】在 VS2015 中访问类成员时出现运行时错误,但在 Linux 上没有【英文标题】:Runtime error when accessing class member in VS2015 but not on Linux 【发布时间】:2017-08-09 08:13:20 【问题描述】:此代码在 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。
【问题讨论】:
因此您为Stru1
分配内存,将其转换为具有不同成员的Stru2*
,并期望一切正常。?
您已经分配了 sinRecv = Stru1(带有“new Stru1”),然后将指针转换为 Stru2。 “新”分配的 sizeof(Stru1),因此尝试取消指向 Stru2 的指针会超出分配的末尾。
Stru2* sro = (Stru2*)simRecv;
-- 从这行代码中删除强制转换。现在仔细阅读the error you get from your compiler。同样的事情here。错误说明了什么?那么你听过你的编译器吗?不,您继续并应用了强制转换来“关闭编译器”。
【参考方案1】:
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;
问题是:这是否在有效的程序空间内?如果是,则不会发生错误,但这并不意味着它是好的。您可能正在其他地方更改变量,从而导致不可预测的结果。
一个例子:
平台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 的附加说明请参阅:What's wrong with cplusplus.com?
【讨论】:
以上是关于在 VS2015 中访问类成员时出现运行时错误,但在 Linux 上没有的主要内容,如果未能解决你的问题,请参考以下文章