Why access violation?

Here is a code example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class A
{
public:
	A()
	{
	}
	
	virtual void Draw()
	{
		int z = 0;
	}
};

class B : public A
{
public:
	void Draw()
	{
		int x = 0;
	}
};

class C
{
public:
	B b;

	C()
	{
		memset(this, 0, sizeof(C));
	}
};

//-----------------------------------------------------------------------------
void main()
{
	C c;
	A *pA = &c.b;
	pA->Draw();  // <------ 0xC0000005: Access violation reading location 0x00000000.
}


I understand that it comes from memset in class C, but why???

Thanks,
Dima
You must never ever use memset or any other dumb memory operation (like memcpy, memcmp, binary file i/o, etc) on a complex type. This is just one of many reasons why.

Since A is polymorphic (has at least 1 virtual function), it has a hidden 'vtable' bundled into it. Among possibly other things, this vtable contains function pointers for all the virtual functions in the class, so it knows what type the object is, as well as what functions to call when a virtual function call occurs.

When you memset the object, you are wiping out the vtable, destroying all that information. Hence the access violation.
Last edited on
Hey, Disch, thank you! Good explanation.

I do memset in constructor as I have a lot of members: pointers and arrays in the class C that I need to set to NULL on initialization. Can you recommend something how to zero out at once all members but do not affect vtable?

With a current code structure, the only solution I could came up with is to declare "b" as a pointer.
Can you recommend something how to zero out at once all members but do not affect vtable?
Assign all of them to 0 in constructor initializer list.
Alternatively you can store all primitive implementation data in member POD struct and zero it out:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class foo
{
    struct {
        primitive_type a;
        primitive_type b;
        primitive_type c;
        primitive_type d;
        primitive_type e;
        //...
    } storage;
    //...
    foo()
    {
        memset(&storage, 0, sizeof(storage));
    }
};
However you should make sure that null pointer really have value of zero in your target architecture :P
similar idea:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class A_vars
{
public:
  type a;
  type b;
  type c;

  A_vars()
  {
    memset(this, 0, sizeof(A_vars));
  }
};

class A: public A_vars
{
...
};

If you have C++11 support.... I believe this is now legal:

1
2
3
4
5
6
7
8
9
class A
{
private:
    int a = 0;
    int b = 0;
    int c = 0;

    // no need to write default constructor
};



But I can't remember whether or not that's correct. Try it and see.


If you are using raw pointers (you said you need to initialize to null) -- you're probably doing it wrong. Raw pointers don't have much use in C++... consider using smart pointers instead (which will default initialize themselves with null so you don't have to)


I do not recommend using memset in any form. It will only work with POD types, and it's very easy to break. memset has no place in C++.
Thank you guys!
I rewrote code like Disch suggested with int a = 0; in constructor.

Thanks!
Dima

I rewrote code like Disch suggested with int a = 0; in constructor.



Errr... if you do that in the constructor then you aren't doing anything.

You need to do it in the class body.
true. I meant in the class body where I declare it.
Topic archived. No new replies allowed.