You gave evidence multiple different ways of an error you almost seem to understand. Why didn't you simply look at the relevant variables and understand the error.
If you care, the relevant part of the valgrind output is:
Quote:
Code:
==11984== Invalid write of size 4
==11984== at 0x8049476: main (cache_sim.c:426)
==11984== Address 0x41d8030 is 8 bytes after a block of size 4,096 alloc'd
|
But that doesn't mean the rest of what valgrind found is safe to ignore. Also you didn't really need valgrind, since the rest of what you posted also identifies the fault.
Quote:
Originally Posted by trist007
This is in C
Code:
else if (cache_index == 255) {
n = replace_array[cache_index];
cache_array[((cache_index * assoc) + assoc) + n] = cache_tag;
}
...
Is this some sort of overflow?
|
Of course.
The value of
((cache_index * assoc) + assoc) + n is obviously greater than the number of elements in cache_array. So when you hit that hardware breakpoint, you should have looked at the values of
cache_index,
assoc and
n to determine which of them is larger than you expected, then find out why.
Quote:
Originally Posted by trist007
If I run it normally it segfaults. It segfaults as a result of replace_array[0] becoming that large value. However, if I use valgrind, the output comes out successfully with no segfault.
|
When you run it normally, replace_array is allocated just 8 bytes later in memory than cache_array. Your code exceeds the size of cache_array (by at least 12 bytes) clobbering those 8 bytes and clobbering at least four more bytes (the first four bytes of replace_array.
When you run with Valgrind, Valgrind inserts extra space between the allocation of cache_array and the allocation of replace_array, so when your program still clobbers beyond the end of cache_array that doesn't affect replace_array.
Quote:
Originally Posted by trist007
I had called malloc to two int *arrays. I malloc'd them one after the other, cache_array and replace_array. This time, I moved one of the malloc's further down the code and now it works fine. How is it that calling malloc on both of the pointers one after the other would cause conflicts like an invalid pointer when calling free()?
|
Two sequential calls to malloc, in a program that hasn't previously released fragmented allocated memory, typically gives you contiguous blocks. The eight bytes immediately after the first block contain control information that will be needed when freeing the second block. When your program clobbers those eight bytes that has no immediate symptom, but later causes the free operation to go wrong.
If the second block is allocated later (after some other unrelated allocation) then that other free operation is the one that will go wrong and maybe you never freed that other chunk.
If you aren't skilled at use of the debugger, you could patch that section of the program to give you info about the bug:
Code:
else if (cache_index == 255) {
n = replace_array[cache_index];
if ( 1024 <= ((cache_index * assoc) + assoc) + n ) {
printf("Bug detected: cache_index=%d, assoc=%d, n=%d\n"
cache_index, assoc, n);
exit(-1); }
cache_array[((cache_index * assoc) + assoc) + n] = cache_tag;
}
I inferred the 1024 from your valgrind output. Hopefully there is some symbolic version of that used when you malloc'ed cache_array. Using that symbolic version is cleaner than the 1024 I put in the above code.
Also, why do you add assoc in that index expression that goes wrong? I understand multiplying by assoc and adding n, but I don't understand the extra add of assoc. That might be the entire cause of the bug.