0

This code works OK when compiled with g++ on Linux, but when I try to execute them in VS 2015 (both debug and release) I receive runtime error. What's wrong with it?

#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;
}

Error: Exception thrown at 0x0000000077A0F23C (ntdll.dll) in ConsoleApplication1.exe: 0xC0000005: Access violation reading location 0x00000FB00188C508.

Stefan
  • 17,448
  • 11
  • 60
  • 79
laslo
  • 57
  • 5
  • 1
    So you allocate memory for `Stru1`, cast it to `Stru2*` which has different members and expect everything to work.? – Gaurav Sehgal Aug 09 '17 at 08:16
  • 1
    You've allocated sinRecv = Stru1 (with "new Stru1") then cast the pointer to a Stru2. The "new" allocated sizeof(Stru1), so trying to deref the pointer to a Stru2 is going off the end of the allocation. – Robinson Aug 09 '17 at 08:16
  • `Stru2* sro = (Stru2*)simRecv;` -- Remove the cast from this line of code. Now **read carefully** [the error you get from your compiler](http://ideone.com/ISu20W). Same thing [here](http://rextester.com/FYCVU59942). What does the error say? So did you listen to your compiler? No, you went ahead and applied a cast to "shut the compiler up". – PaulMcKenzie Aug 09 '17 at 09:40

1 Answers1

2
Stru2* sro = (Stru2*)simRecv;

simRecv is a Stru1, so your unsafe cast to Stru2 is invalid in this line.

In this line you create this Stru1,

 Stru1* simRecv = new Stru1;

Here Stru1 is assigned the memory needed to create a Stru1, which is smaller than a Stru2.

By doing:

Stru2* sro = (Stru2*)simRecv;

You are just saying: I have this "thing" and treat it as a Stru2. But there hasn't been a new Stru2 created anywhere so the object just isn't there.

It is basically the same as saying

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

The reason that it might work on a different platform can be due to a different memory allocation of the platform.

As for the analogy: you might have reached the end of the wall and hence don't hurt your head, but you are not inside the house and you won't leave your wallet there.

For example, this line will eventually point to somewhere:

sro->dwMem3 = 77; 

The question is: is this within valid program space? If it is, no error will occur, but that doesn't mean it is good. You are probably altering a variable, somewhere else, leading to unpredictable results.

An example:

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

If you assign a Stru2 (by actually creating it) in the first place, all will be good:

Stru1* simRecv = (Stru1*) new Stru2;

Having said that; these cast are considered unsafe (for now obvious reasons). The alternative is to use, for example a static_cast. It will make sure you'll get a build error when trying to do something "illegal".

http://www.cplusplus.com/doc/tutorial/typecasting/

additional note about cplusplus see: What's wrong with cplusplus.com?

Stefan
  • 17,448
  • 11
  • 60
  • 79