Valgrind invalid read / write errors, no solution found in other issues

I am writing C code for homework that replicates main memory with a dynamic array of memory segments.

These memory segments come from another interface, which itself is a static uint32_ts array.

My main memory interface is called heapmem (like in a heap memory), and I get weird valgrind read / write errors since switching. Before chewing on me, I looked and researched, and I come to SO as a last resort.

Here is the error

==30352== Invalid write of size 8 ==30352== at 0x401661: HeapMem_map (heapmem.c:84) ==30352== by 0x400E74: map (um.c:109) ==30352== by 0x4010FD: runOpcode (um.c:182) ==30352== by 0x4011A1: UM_run (um.c:209) ==30352== by 0x400A71: main (main.c:10) ==30352== Address 0x4c53b00 is 0 bytes after a block of size 16 alloc'd ==30352== at 0x4A0610C: malloc (vg_replace_malloc.c:195) ==30352== by 0x401425: HeapMem_new (heapmem.c:32) ==30352== by 0x400ABE: UM_new (um.c:31) ==30352== by 0x400A64: main (main.c:8) ==30352== ==30352== Invalid read of size 8 ==30352== at 0x401787: HeapMem_put (heapmem.c:114) ==30352== by 0x400D38: sstore (um.c:90) ==30352== by 0x401090: runOpcode (um.c:167) ==30352== by 0x4011A1: UM_run (um.c:209) ==30352== by 0x400A71: main (main.c:10) ==30352== Address 0x4c53b00 is 0 bytes after a block of size 16 alloc'd ==30352== at 0x4A0610C: malloc (vg_replace_malloc.c:195) ==30352== by 0x401425: HeapMem_new (heapmem.c:32) ==30352== by 0x400ABE: UM_new (um.c:31) ==30352== by 0x400A64: main (main.c:8) ==30352== ==30352== Invalid read of size 8 ==30352== at 0x401956: car_double (heapmem.c:151) ==30352== by 0x401640: HeapMem_map (heapmem.c:82) ==30352== by 0x400E74: map (um.c:109) ==30352== by 0x4010FD: runOpcode (um.c:182) ==30352== by 0x4011A1: UM_run (um.c:209) ==30352== by 0x400A71: main (main.c:10) ==30352== Address 0x4c53b00 is 0 bytes after a block of size 16 alloc'd ==30352== at 0x4A0610C: malloc (vg_replace_malloc.c:195) ==30352== by 0x401425: HeapMem_new (heapmem.c:32) ==30352== by 0x400ABE: UM_new (um.c:31) ==30352== by 0x400A64: main (main.c:8) ==30352== ==30352== Invalid read of size 8 ==30352== at 0x40174A: HeapMem_get (heapmem.c:108) ==30352== by 0x400CD9: sload (um.c:86) ==30352== by 0x401079: runOpcode (um.c:164) ==30352== by 0x4011A1: UM_run (um.c:209) ==30352== by 0x400A71: main (main.c:10) ==30352== Address 0x4c7e0f0 is 0 bytes after a block of size 4,096 alloc'd ==30352== at 0x4A0610C: malloc (vg_replace_malloc.c:195) ==30352== by 0x401923: car_double (heapmem.c:148) ==30352== by 0x401640: HeapMem_map (heapmem.c:82) ==30352== by 0x400E74: map (um.c:109) ==30352== by 0x4010FD: runOpcode (um.c:182) ==30352== by 0x4011A1: UM_run (um.c:209) ==30352== by 0x400A71: main (main.c:10) 

Here are the code functions giving me errors:

 // Heap Memory Structure struct T { Stack_T SegID_stack; MemSeg_T* HeapMem_car; int length, highest; }; // Create a new heap memory structure T HeapMem_new (MemSeg_T program) { assert (program); T retHeap = malloc(sizeof(*retHeap)); Stack_T structStack = Stack_new (); retHeap->length = INIT_SIZE; retHeap->highest = 0; MemSeg_T* structCar = malloc(INIT_SIZE * sizeof(*structCar)); // Fill the array with NULL ptrs for (int i = 0; i < INIT_SIZE; i++) { structCar[i] = NULL; } retHeap->HeapMem_car = structCar; retHeap->SegID_stack = structStack; // We'll be using the map function to initialize // the heap with a program at the 0th segment. HeapMem_map (retHeap, MemSeg_length (program)); retHeap->HeapMem_car[PROGRAM_LOC] = program; return retHeap; } // Line 84 heapmem->HeapMem_car[toMap] = segment; // Line 114 MemSeg_T segToPut = heapmem->HeapMem_car[toPut]; // Line 151 newCar[i] = heapmem->HeapMem_car[i]; // Line 108 MemSeg_T wordSeg = heapmem->HeapMem_car[toGet]; 

The rest of the code is available here .

+4
source share
1 answer

First, a small section of one of your mistakes:

 ==30352== Invalid write of size 8 ==30352== at 0x401661: HeapMem_map (heapmem.c:84) ==30352== by 0x400E74: map (um.c:109) ==30352== by 0x4010FD: runOpcode (um.c:182) ==30352== by 0x4011A1: UM_run (um.c:209) ==30352== by 0x400A71: main (main.c:10) ==30352== Address 0x4c53b00 is 0 bytes after a block of size 16 alloc'd ==30352== at 0x4A0610C: malloc (vg_replace_malloc.c:195) ==30352== by 0x401425: HeapMem_new (heapmem.c:32) ==30352== by 0x400ABE: UM_new (um.c:31) ==30352== by 0x400A64: main (main.c:8) 

Please note that the bottom of this list indicates where the distribution occurred. The top tells you how it was misused. In this case, you will go to the end of the requested allocation of 8 bytes.

You will notice that all overflows in this and the remaining violations exceed their means in exactly the same offset (8 bytes). Further consideration of the reference code shows that it is always the same array. Actually, this is good, since it is very likely that the problem is simply incorrectly calculated, how the data elements are present and reach one or two outside the legal space.

In this case, the element that is violated is represented by a dynamically allocated list of pointers ( heapmem->HeapMem_car[] ). Running on a machine with 64-bit pointers will do each of the 8-byte characters, so you are most likely just one after the other in the last available element of this distribution and in C, which usually always means indicate that you selected N elements, and then got access to array[N] , forgot the limit of N-1 . All of the above access violations seem to be centered around the belief that the indexes in this array are not out of bounds, but valgrind reports that they are. I suggest you skip some assert () element to these access points and break the violation to find out how you got there. Oh wait .. valgrind already has this information for you. Look at this beautiful call stack. Hmmm ...

So why does he even work with these violations? A number of possibilities. If you do not go far beyond the allocated memory - and all addresses are 0 bytes after - (after all, these are pointers, so pray that they are NULL) there is a good chance that you will not overwrite important data and the program seems to work. Until the allocation lands somewhere else and you cross the page boundary. Overload it and kerboom.

Thanks to Daniel Fisher for contributing to the second part of this answer (why this works).

+10
source

Source: https://habr.com/ru/post/1447321/


All Articles