2017-08-09 49 views
0

时相克在Linux ++编译此代码工作正常,但是当我尝试在2015年VS(包括调试和释放)来执行他们,我收到运行时错误。它出什么问题了?运行时错误访问时,在VS2015类成员,但不是在Linux上

#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中)抛出:0000005:访问冲突读取位置0x00000FB00188C508。

+1

所以你分配内存'Stru1',将其转换为'Stru2 *'它有不同的成员和所期望的一切工作。? –

+1

您已经分配了sinRecv = Stru1(带有“new Stru1”),然后将指针投射到Stru2。 “新”分配的sizeof(Stru1),所以试图去指向Stru2的指针正在分配结束。 – Robinson

+0

'Stru2 * sro =(Stru2 *)simRecv;' - 从这行代码中删除转换。现在**仔细阅读** [您从编译器得到的错误](http://ideone.com/ISu20W)。同样的事情[这里](http://rextester.com/FYCVU59942)。错误说的是什么?你是否听过你的编译器?不,你继续申请一个演员阵容,“关闭编译器”。 – PaulMcKenzie

回答

2
Stru2* sro = (Stru2*)simRecv; 

simRecvStru1,让您的不安全投给Stru2是在这一行无效。

在这一行,你创建这个Stru1

Stru1* simRecv = new Stru1; 

这里Stru1被分配到创建Stru1所需的内存,这比Stru2小。

这样做:

Stru2* sro = (Stru2*)simRecv; 

你只是说:我有这样的“东西”,并把它作为一个Stru2。但是在任何地方都没有创建new Stru2,所以对象不在那里。

它基本上是相同的话说

I have a large wall, but I'll treat it as a house and expect a door in it.

的原因,它在不同的平台威力的工作可以是由于平台的不同内存分配。

至于类比:你可能可能已经到达墙的尽头,因此不会伤到你的头,但你不是在房子里面,你不会离开你的钱包在那里。

例如,该行最终将指向某个地方:

的问题是:这是有效的程序空间内?如果是的话,不会发生错误,但这并不意味着它是好的。您可能正在改变其他地方的变量,导致不可预知的结果。

一个例子:

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?

相关问题