Reputation: 1
I have a program which is segfaulting at a specific line:
uint64_t smaller_num = *(uint64_t*)(smaller_base+index);
GDB successfully catches the segfault allowing me to debug the issue. However, if I run the line from the GDB prompt, no memory access violation occurs:
(gdb) p smaller_num = *(uint64_t*)(smaller_base+index)
Can anyone provide some suggestions on how to debug this issue? I am at a loss of words and ideas because I verified that the memory at smaller_base+index exists. Can it be something with the casting?
Thanks in advance.
EDIT: providing more code but it really is that simple. I have heavily edited code to show the point of the indexing.
uint64_t ** find_difference(unsigned char * larger_base,
uint64_t size,
unsigned char * smaller_base,
uint64_t tmap_size)
{
uint64_t len = size < tmap_size?size:tmap_size;
uint64_t index=0;
while(index<len)
{
uint64_t larger_num = *(uint64_t*)(larger_base+index);
uint64_t smaller_num = *(uint64_t*)(smaller_base+index);
if(larger_num > smaller_num)
{
... do stuff
}
index++;
}
...
}
Edit#2: Now that I am thinking about it, is it poissible that the pointer dereference goes beyond len? It was my understanding that x86 numbers are stored from high to low addresses. Thus in memory, a number 0x01020304 is stored as 0x04 0x03 0x02 0x01. Is this correct? If this is not true, the deference would go beyond the end of the buffer. However, in GDB I verified the address is accessible.
Upvotes: 0
Views: 232
Reputation: 7228
Your original pointer arithmetic added index to a (unsigned char *) before casting it to uint64_t causing an unaligned memory load, i.e. trying to dereference an (uint64_t *) from an address that is not a multiple of 8. This works in the debugger but causes a SEGFAULT in your program.
Upvotes: 0
Reputation: 1335
I do not know how you use find_difference() function and what values of parameters passed to the function, but I suspect that your pointer arithmetic is wrong.
You are incrementing large_base and smaller_base by 1 and casting resulting address as u64*. If size is in bytes, then you should check that large_base+index+8 < size.
Upvotes: 1