An interesting (to me, who has no life I guess) update on this problem:
First, the cppcheck tool I used above is a static source code checker which means it analyzes the source code as-is; you don't have to compile anything into the app, you don't have to run it, etc. This I think is more on the lines of what the OP was looking for WRT CodeBlocks.
However one of my favorite tools for finding non-obvious memory and resource issues is Valgrind. Valgrind falls into the category of tools that examine a running app and watch for memory leaks, overruns, etc that way. Normally this approach is some powerful mojo but in this particular case it fell on its face. When run as written above (well in my source I just made the test a separate function and called it from main()), when the app gets to the first actual bug (for loop that iterates beyond the end of the array) the program just stops, requiring a Ctrl-C to break it. GDB acted the same way and electric fence acted the same way as well. The print statement just before it never resulted in something going to the screen. This is and of itself is a bug too when viewed in the context of debugging this app because there is no endl at the end so the buffers are not flushed and since the next line stops the program, the line of text never appears (endl, in addition to supplying a carriage return/line feed also flushes your buffers). Now here is the interesting part: to problem of the end-of-array overwrite means that the address of array[24+1] is somewhere in the code so by overwriting that, you are likely stepping on other code preventing the app from finishing. As a sort of test, I added the following just after that for loop:
Code:
int dodgyIndex =-1;
TargetArray[dodgyIndex] = 20;
Slightly altering the memory footprint of the app and even with the bad for() loop it ran to completion, probably because I gave it a non-essential bit of code to step on. The same or similar results could have been achieved by allocating TargetArray on the heap via new or making it static. This points to a subtle yet nice bullet to have in your debugging armament: if you suspect a memory block is being violated in any way, change where it is being allocated. If it is an automatic variable like this, create it on the heap via new and see if your symptoms change. If it is created with malloc/new, change it to a stack-based variable and see what happens.
This can give you some simple yet vital clues as to what is going on. Interestingly enough, if you look at the original code and insert my dodgyIndex test immediately after the for loop (but before any of the output lines) TargetArray[25] reports a value of -1, not 20 as you would expect...however even though the app can make it to the finish line, because of the way the long array is allocated valgrind and electric fence cannot see the bugs. However I altered the test a little to push the array onto the heap by allocating it with new and passing it to the test function, rebuilt and ran it under valgrind once again and got the following output (extraneous output removed):
Code:
==6098== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 21 from 8)
==6098==
==6098== 1 errors in context 1 of 4:
==6098== Invalid read of size 4 <<== attempt to display TargetArray-[25]
==6098== at 0x8048ECB: testBounds(long*) (boundscheck_main.cpp:35)
==6098== by 0x804909D: main (boundscheck_main.cpp:71)
==6098== Address 0x42ce0d4 is 0 bytes after a block of size 100 alloc'd
==6098== at 0x4025024: operator new[](unsigned int) (vg_replace_malloc.c:258)
==6098== by 0x804908F: main (boundscheck_main.cpp:70)
==6098==
==6098==
==6098== 1 errors in context 2 of 4:
==6098== Invalid write of size 4 <<== my write of a value to TargetArray[-1]
==6098== at 0x8048E3E: testBounds(long*) (boundscheck_main.cpp:31)
==6098== by 0x804909D: main (boundscheck_main.cpp:71)
==6098== Address 0x42ce06c is 4 bytes before a block of size 100 alloc'd
==6098== at 0x4025024: operator new[](unsigned int) (vg_replace_malloc.c:258)
==6098== by 0x804908F: main (boundscheck_main.cpp:70)
==6098==
==6098==
==6098== 1 errors in context 3 of 4:
==6098== Invalid write of size 4 <<== OPs write to element TargetArray[25]
==6098== at 0x8048E19: testBounds(long*) (boundscheck_main.cpp:29)
==6098== by 0x804909D: main (boundscheck_main.cpp:71)
==6098== Address 0x42ce0d4 is 0 bytes after a block of size 100 alloc'd
==6098== at 0x4025024: operator new[](unsigned int) (vg_replace_malloc.c:258)
==6098== by 0x804908F: main (boundscheck_main.cpp:70)
==6098==
So depending on your situaion, Valgrind can hand you the bugs on a silver platter or provide a false sense of security.
Electric fence did a little better and a lot worse; yes it detected the first memory overwrite but didn't tell you where it was but it did through a segfault which stinks if thats all you have but if you ran the same app in GDB the segfault would cause a stack trace dump which would be helpful plus it more or less pointed out the first line with an error on it:
Code:
boundscheck_test 1.0
Electric Fence 2.1 Copyright (C) 1987-1998 Bruce Perens.
Testing: boundscheck
Test 1:
TargetArray[0]: 10
TargetArray[24]: 10
Attempting at assigning values beyond the upper bound...
Program received signal SIGSEGV, Segmentation fault.
0x08048e79 in testBounds (TargetArray=0xb7ed8f9c) at /home/jeff/dev/bounds/boundscheck_main.cpp:29
29 TargetArray[i] = 20; // asigning my fail for element 25
I know, TMI...