I have a question about dynamic array (c++11)

Hi, I'm a sophomore student of CS and preparing for a coding competition, But I meet some problems.
My code is here. I run it on Dev C++ 5.11:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
	int *rowtemp = new int(0);
	int *columntemp = new int(0);

	cout<<"row's size':"<<row<<endl;
	cout<<"column's size:"<<column<<endl;
	
	for (int o = 0; o < row; o++)
		rowtemp[o] = o;
	for (int k = 0; k < column; k++)
		columntemp[k] = k;
	
	cout<<"rowtemp:";	
	for (int b = 0; b < row; b++)
	{
			cout<<rowtemp[b]<<" ";
	}
	cout<<endl;
	cout<<"columntemp:"	;
	for (int b = 0; b < column; b++)
	{
			cout<<columntemp[b]<<" ";
	}
	cout<<endl;


I know the codes have some problems, "rowtemp" is not an array. I did not declare it as an arrary. But when I run these codes, Here comes something strange:

row's size':100
column's size:100
rowtemp:0 1 2 3 4 5 6 7 0 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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
columntemp:0 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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99

The result of "rowtemp" is not my anticipate, but the result of "columntemp" is exactly correct. In the beginning, I assumed it was an accident. But the truth is, when I run these codes in an online coding platform, I got the same result. It's not random.
I just wondering why "rowtemp" began with 0 1 2 3 4 5 6 7 0, but "columntemp" didn't?
Thanks a lot.
The following is my whole program.
I'm not native, so my English may have some gramma problems, sorry about that.

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#include<iostream>
using namespace std;


int main()
{
	int row;
	int column;

	cin >> row;
	cin >> column;

	int **data = new int*[row];
	for (int i = 0; i < row; i++)
		data[i] = new int[column];


	for (int i = 0; i < row; i++)
	{
		for (int n = 0; n < column; n++)
		{
			int temp;
			cin >> temp;
			data[i][n] = temp;
		}
	}


	int *rowtemp = new int(0);
	int *columntemp = new int(0);

	cout<<"row's size':"<<row<<endl;
	cout<<"column's size:"<<column<<endl;
	
	for (int o = 0; o < row; o++)
		rowtemp[o] = o;
	for (int k = 0; k < column; k++)
		columntemp[k] = k;
	
	cout<<"rowtemp:";	
	for (int b = 0; b < row; b++)
	{
			cout<<rowtemp[b]<<" ";
	}
	cout<<endl;
	cout<<"columntemp:"	;
	for (int b = 0; b < column; b++)
	{
			cout<<columntemp[b]<<" ";
	}
	cout<<endl;
	
	int ops;
	cin >> ops;
	for (int m = 0; m < ops; m++)
	{
		int x, y, z;
		cin >> x >> y >> z;
		int temp;
		if (x == 0)
		{
			temp = rowtemp[y - 1];
			rowtemp[y - 1] = rowtemp[z - 1];
			rowtemp[z - 1] = temp;
		}
		else if (x == 1)
		{
			temp = columntemp[y - 1];
			columntemp[y - 1] = columntemp[z - 1];
			columntemp[z - 1] = temp;
		}

	}




	for (int a = 0; a < row; a++)
	{
		for (int b = 0; b < column; b++)
		{
			if (b != column - 1)
				cout << data[rowtemp[a]][columntemp[b]] << " ";
			else
				cout << data[rowtemp[a]][columntemp[b]];
		}
		cout << '\n';
	}



	return 0;
}
Last edited on
I know the codes have some problems, "rowtemp" is not an array. I did not declare it as an arrary. But when I run these codes,

anything can happen. Undefined behaviour. Not legal.
I know it's not legal, but it shows the same results on different platforms. I don't think it's a random thing. There are some unanticipated rules in it, although it may not be meaningful. I wonder how it happened.
Of course it is not truly random. Real Random is hard to generate.

Compilers and OS are created by programmers. There is no rule on how to react if a girl smiles to you, but do you think that the reactions of stererotypic programmers have huge variance?


Dev C++ is not a compiler. It uses a compiler.
Online platform is not a compiler. It uses a compiler.
Can you tell that they don't run same compiler and don't run on same OS?
> 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.

That’s an awesome explanation, salem c. Many thanks for it!
Thanks a lot! That solves my question! Awesome explanation!
Topic archived. No new replies allowed.