Issue with Skipped malloc Breakpoints in GDB When Using finish and continue
Puspaul Halder via Gdb <[email protected]>
| Newsgroups | gmane.comp.gdb.devel |
|---|---|
| Message-ID | <CADXRgKajnNy1sJ58=z_=kbOjtucd9SrQif9boccmO+uX0_rKcA@mail.gmail.com> |
Hey Team,
I have a simple requirement:
- Track the total memory allocated (malloc) and freed (free).
- Capture backtraces of all malloc and free calls (for now, logging can
be ignored).
*Current Approach*
1.
*For malloc*:
- I need every malloc call to complete execution.
- After completion, I retrieve $rax and use malloc_usable_size($rax)
to determine the actual allocated memory.
2.
*For free*:
- This is simpler since malloc_usable_size($rdi) gives the size being
freed.
Manually continuing execution from the GDB prompt works fine. However, my
debugging case involves *thousands* of malloc and free calls, so I want
this to run *automatically* without user intervention.
*The Issue*
- When I add continue inside hookpost-myfinish, I observe *skipped
malloc breakpoints*.
- As a result, malloc_count, free_count, total_malloced, and total_freed
become incorrect.
- I suspect this happens when *consecutive malloc calls* occur:
- finish from malloc returns execution to main(), and another continue
causes the *next malloc entry breakpoint to be skipped*.
*Reproduction Steps*
1. *Using gdb_commands.txt* → Works correctly (manual continuation
required).
2. *Using gdb_commands_continue.txt* → Causes alternate malloc calls to
be skipped, leading to incorrect tracking.
This seems to be due to how continue interacts with finish, but I’m unsure
of the best way to *ensure every malloc and free call is properly accounted
for* without skipping breakpoints.
*Request*
Could someone help me understand why continue is skipping alternate malloc
calls and suggest a reliable way to handle this?
I've attached:
- code.c → Sample test code.
- gdb_commands.txt → Correct execution (manual continuation).
- gdb_commands_continue.txt → Shows skipped malloc calls with continue.
Would appreciate any insights or alternative approaches!
Thanking You,
Puspaul Halder
gdb_commands.txt
(text/plain, 870 B)
set unwindonsignal off
set $mc = 0
set $fc = 0
set $mallocsize = 0
set $in_malloc = 0
set $total_malloced = 0
set $total_freed = 0
b memory_test.c:8
b malloc
b free
disable 2 3
commands 1
silent
enable 2 3
continue
end
commands 2
set $mc = $mc + 1
set $mallocsize = $rdi
printf "Asked to malloc %d bytes\n", $mallocsize
set $in_malloc = 1
myfinish
end
commands 3
set $fc = $fc + 1
if ($rdi)
set $total_freed = $total_freed + (size_t)malloc_usable_size($rdi)
printf "Freed %d bytes \n ", (size_t)malloc_usable_size($rdi)
end
continue
end
define myfinish
finish
end
define hookpost-myfinish
set $total_malloced = $total_malloced + (size_t)malloc_usable_size($rax)
printf "Actually malloced %d bytes and total malloced till now is %d \n", (size_t)malloc_usable_size($rax), $total_malloced
set $in_malloc = 0
end
code.c
(application/octet-stream, 1.9 KB)
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h> // Required for malloc_usable_size
int main() {
printf("Starting memory allocation test...\n");
// Allocate memory blocks of different sizes
void *ptr1 = malloc(32);
printf("ptr1 allocated at address: %p\n", ptr1);
free(ptr1);
printf("ptr1 freed");
void *ptr2 = malloc(64);
printf("ptr2 allocated at address: %p\n", ptr2);
printf("ptr2 allocated at address: %p\n", ptr2);
printf("ptr2 allocated at address: %p\n", ptr2);
printf("ptr2 allocated at address: %p\n", ptr2);
printf("ptr2 allocated at address: %p\n", ptr2);
printf("ptr2 allocated at address: %p\n", ptr2);
printf("ptr2 allocated at address: %p\n", ptr2);
printf("ptr2 allocated at address: %p\n", ptr2);
printf("ptr2 allocated at address: %p\n", ptr2);
printf("ptr2 allocated at address: %p\n", ptr2);
printf("ptr2 allocated at address: %p\n", ptr2);
printf("ptr2 allocated at address: %p\n", ptr2);
void *ptr3 = malloc(128);
printf("ptr3 allocated at address: %p\n", ptr3);
free(ptr2);
free(ptr3);
void *ptr4 = malloc(128);
printf("ptr4 allocated at address: %p\n", ptr4);
void *ptr5 = malloc(128);
printf("ptr5 allocated at address: %p\n", ptr5);
void *ptr6 = malloc(256);
printf("ptr6 allocated at address: %p\n", ptr6);
void *ptr7 = malloc(256);
void *ptr8 = malloc(256);
void *ptr9 = malloc(256);
void *ptr10 = malloc(256);
void *ptr11 = malloc(256);
void *ptr12 = malloc(256);
void *ptr13 = malloc(256);
void *ptr14 = malloc(256);
void *ptr15 = malloc(256);
void *ptr16 = malloc(256);
free(ptr5);
free(ptr4);
free(ptr6);
free(ptr7);
free(ptr8);
free(ptr9);
free(ptr10);
free(ptr11);
free(ptr12);
free(ptr13);
free(ptr14);
free(ptr15);
free(ptr16);
printf("Memory allocation test completed.\n");
return 0;
}
gdb_commands_continue.txt
(text/plain, 870 B)
set unwindonsignal off
set $mc = 0
set $fc = 0
set $mallocsize = 0
set $in_malloc = 0
set $total_malloced = 0
set $total_freed = 0
b memory_test.c:8
b malloc
b free
disable 2 3
commands 1
silent
enable 2 3
continue
end
commands 2
set $mc = $mc + 1
set $mallocsize = $rdi
printf "Asked to malloc %d bytes\n", $mallocsize
set $in_malloc = 1
myfinish
end
commands 3
set $fc = $fc + 1
if ($rdi)
set $total_freed = $total_freed + (size_t)malloc_usable_size($rdi)
printf "Freed %d bytes \n ", (size_t)malloc_usable_size($rdi)
end
continue
end
define myfinish
finish
end
define hookpost-myfinish
set $total_malloced = $total_malloced + (size_t)malloc_usable_size($rax)
printf "Actually malloced %d bytes and total malloced till now is %d \n", (size_t)malloc_usable_size($rax), $total_malloced
set $in_malloc = 0
end