1
#include <iostream>

using namespace std;

struct A
{
    int a, b;
};

struct B
{
    int a;
};

int main()
{
    A * pa = (A *)malloc(sizeof(B));
    int c = 5;
    pa -> a = 3;
    cout << pa -> a << endl;
    pa -> b = 0;
    cout << pa -> b << endl;
    cout << c << endl;
    return 0;
}

I run this code with VC++ 2012. It doesn't generate any error message.

I think pa -> b will access memory block outbound. Heap corruption should occur! But actually, nothing happened in both debug and release modes.

But since int c immediately follows A * pa; I think in memory, pa -> b will access int c.

The output of the program is: 3 4 5

Can anyone help explain this?


If I add "free(pa);" at the end of the main: +under debug mode, it will cause HEAP CORRUPTION ERROR. +under release mode, nothing still happens.

trincot
  • 317,000
  • 35
  • 244
  • 286
Zachery
  • 131
  • 2
  • 8
  • 7
    Undefined behavior means anything can happen. – Luchian Grigore Apr 12 '13 at 08:50
  • How are you determining that the heap isn't corrupted in some way? In general you can't expect an error message for this. Sometimes the runtime can detect corruption and warn you but the runtime can't and doesn't detect every instance of writing outside of memory bounds. – jcoder Apr 12 '13 at 08:54
  • 1
    Probably this is due to structure packing for alignment masking the problem. – Randy Howard Apr 12 '13 at 08:57
  • Oh, I see. Undefined means anything possible. – Zachery Apr 12 '13 at 09:01
  • Heap corruption detection is not part of the standard, and those who created this detection mechanism tried their best to inform the user about the problem. – Dialecticus Apr 12 '13 at 09:06
  • Your reasoning about the `pa->b` access corrupting `c` is incorrect. This is because `pa` is pointing to memory on the heap, while `c` lives on the stack, so `c` is in a totally different region of memory. – effect Nov 12 '21 at 20:32

2 Answers2

1

Undefined behaviour means that anything can happen. In particular, no diagnostic is required.

One practical way to find bugs of this type is by using a tool like Valgrind:

$ valgrind ./a.out
a=3
==37240== Invalid write of size 4
==37240==    at 0x100000E1D: main (test.c:22)
==37240==  Address 0x10001b184 is 0 bytes after a block of size 4 alloc'd
==37240==    at 0x5237: malloc (in /usr/local/Cellar/valgrind/3.8.1/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
==37240==    by 0x100000DD2: main (test.c:19)
==37240== 
==37240== Invalid read of size 4
==37240==    at 0x100000E28: main (test.c:23)
==37240==  Address 0x10001b184 is 0 bytes after a block of size 4 alloc'd
==37240==    at 0x5237: malloc (in /usr/local/Cellar/valgrind/3.8.1/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
==37240==    by 0x100000DD2: main (test.c:19)
==37240== 

There are similar tools for Windows: Is there a good Valgrind substitute for Windows?

Community
  • 1
  • 1
NPE
  • 486,780
  • 108
  • 951
  • 1,012
0

Heap corruption can only be detected when you enter some heap function. In this case you enter a heap function only at the beginning, when heap is still uncorrupted. Try to delete structure pointed to pa before returning from main, and see what happens.

Dialecticus
  • 16,400
  • 7
  • 43
  • 103
  • You are right. After i insert a "free(pa)" at the end of the program, error occurs! Debug error! HEAP CORRUPTION DETECTED! CRT detects wrote to memory after the end of heap. – Zachery Apr 12 '13 at 09:10
  • Heap corruption detection is only performed in debug build. In release builds it's removed for performance reasons. For more details please visit [MSDN](http://msdn.microsoft.com/en-us/library/974tc9t1%28v=vs.71%29.aspx) – Dialecticus Apr 12 '13 at 09:24
  • I also heard that the heap under debug and release mode is different! Heap under debug will allocate more memory as specified by programmer. – Zachery Apr 12 '13 at 09:28