Consider the following pretty simple C++ code:
#include <algorithm>
#include <iostream>
using namespace std;
int main()
{
int a[7] = {1, 2, 3, 4, 5, 6, 7};
int b[7];
copy(a, a+7, b);
for (int i=0; i<8; ++i)
cout << b[i] << endl;
}
Now here’s what I get when I load this code in gdb:
(gdb) b 1
Breakpoint 1 at 0x100000a64: file stdcopy.cpp, line 1.
(gdb) r
Starting program: /Users/Babai/pastebin/a.out
Reading symbols for shared libraries ++......................... done
Breakpoint 1, main () at stdcopy.cpp:7
7 int a[7] = {1, 2, 3, 4, 5, 6, 7};
(gdb) n
9 copy(a, a+7, b);
(gdb) s
std::copy<int*, int*> (__first=0x7fff5fbffb8c, __last=0x7fff5fbffba8, __result=0x7fff5fbffb70) at stl_algobase.h:398
398 const bool __in = __is_normal_iterator<_InputIterator>::__value;
(gdb) bt
#0 std::copy<int*, int*> (__first=0x7fff5fbffb8c, __last=0x7fff5fbffba8, __result=0x7fff5fbffb70) at stl_algobase.h:398
#1 0x0000000100000acd in main () at stdcopy.cpp:9
(gdb) up
#1 main () at stdcopy.cpp:10
10 for (int i=0; i<8; ++i)
(gdb) p &a
$1 = (int (*)[7]) 0x7fff5fbffb8c
(gdb) p a + 7
$2 = (int *) 0x7fff5fbffba8
I don’t see any valgrind errors in this code and I am wondering why. The array a has 7 elements and accessing up to a + 6 is fine, but why is valgrind not showing a + 7 as a valid error?
Going past the end of the array results in Undefined Behaviour, meaning that anything could happen. However, your pointer into the array, is allowed to go one past the array, if the pointer is not dereferenced.
This is allowed so that you can check for end of an array, and it is used in containers with iterators. The
end()function for a container iterator points to one past the end. This however never get’s dereferenced, else you’re in Undefined Behaviour land.