> I just wondering why "rowtemp" began with 0 1 2 3 4 5 6 7 0, but "columntemp" didn't?
There are a couple of things to remember when you have memory overruns like this
1. Last one wins; the second 0 is really the start of columntemp, not the remains of rowtemp
2. You generally don't see anything wrong until the next delete / new call.
The memory pool is a chain of memory blocks arranged as
<C><D><C><D><C><D><C><D><C><D>
C = a control block used by the allocator to manage what is allocated and what is free.
D = a data block either in use by your program, or previously used by your program (free, may be reallocated later).
If you scribble past the end of your allocated <D>, you trash a <C> block. After that, it's only a matter of time before it all comes crashing down.
Why 8 ints you ask?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
$ cat bar.cpp
#include <iostream>
int main()
{
int *rowtemp = new int(0);
int *columntemp = new int(0);
std::cout << "Row starts at " << reinterpret_cast<void*>(rowtemp) << std::endl;
std::cout << "Col starts at " << reinterpret_cast<void*>(columntemp) << std::endl;
return 0;
}
$ g++ bar.cpp
$ ./a.out
Row starts at 0x166ac20
Col starts at 0x166ac40
|
Like for you, adjacent allocations are 32 bytes apart, even for just one int. 32 bytes being exactly enough room for 8 integers.
Remember, these 32 bytes contain both a <C> and a <D>
So going back to your program, run it in valgrind (your google search word of the day).
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 41
|
$ g++ -g -Wall foo.cpp
$ valgrind ./a.out
==8075== Memcheck, a memory error detector
==8075== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==8075== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==8075== Command: ./a.out
==8075==
2
2
2
2
2
2
row's size':2
column's size:2
==8075== Invalid write of size 4
==8075== at 0x400C57: main (foo.cpp:36)
==8075== Address 0x5ab71b4 is 0 bytes after a block of size 4 alloc'd
==8075== at 0x4C2E0EF: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8075== by 0x400BC0: main (foo.cpp:29)
==8075==
==8075== Invalid write of size 4
==8075== at 0x400C85: main (foo.cpp:38)
==8075== Address 0x5ab7204 is 0 bytes after a block of size 4 alloc'd
==8075== at 0x4C2E0EF: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8075== by 0x400BD4: main (foo.cpp:30)
==8075==
==8075== Invalid read of size 4
==8075== at 0x400CBF: main (foo.cpp:43)
==8075== Address 0x5ab71b4 is 0 bytes after a block of size 4 alloc'd
==8075== at 0x4C2E0EF: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8075== by 0x400BC0: main (foo.cpp:29)
==8075==
rowtemp:0 1
==8075== Invalid read of size 4
==8075== at 0x400D21: main (foo.cpp:49)
==8075== Address 0x5ab7204 is 0 bytes after a block of size 4 alloc'd
==8075== at 0x4C2E0EF: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8075== by 0x400BD4: main (foo.cpp:30)
==8075==
columntemp:0 1
|
==8075== Invalid write of size 4
==8075== at 0x400C57: main (foo.cpp:36)
This is the line of code that wrote where it shouldn't.
> rowtemp[o] = o;
==8075== Address 0x5ab71b4 is 0 bytes after a block of size 4 alloc'd
==8075== at 0x4C2E0EF: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8075== by 0x400BC0: main (foo.cpp:29)
This is the stack trace to where the memory was allocated.
> int *rowtemp = new int(0);
You look at both, then decide whether to fix the amount you allocate, or fix the amount you ended up trying to write to.