在VS2015中访问类成员但在Linux上访问时没有运行时错误

时间:2017-08-09 08:13:21

标签: c++ visual-studio-2015

在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。

1 个答案:

答案 0 :(得分:2)

Stru2* sro = (Stru2*)simRecv;

simRecvStru1,因此您对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?