如何在64位NASM中正确使用malloc()与free()函数?
free() with C Standard Library Alright, let's cut through the conflicting 32-bit/C-focused resources and get straight to the correct free() implementation for your 64-bit NASM setup. First, let's confirm your malloc() approach is on the right track (since you mentioned you think it's correct), then dive into free().
Key Background: 64-bit System V AMD64 Calling Convention
First, let's recap the critical rules for calling C standard library functions in 64-bit NASM—this is where most outdated 32-bit content trips people up:
- The first (and only, for
malloc/free) function argument goes in therdiregister. - Function return values are stored in
rax(formalloc, this is the allocated memory pointer). - The stack must be 16-byte aligned immediately before calling any C function.
- No need to clean up the stack after the call (unlike 32-bit cdecl); the caller doesn't pop arguments since they're passed in registers.
Confirming Your malloc() Implementation
Just to be thorough, here's the correct pattern for allocating 8000 bytes—this matches what you likely have, but it's good to verify:
; Allocate 8000 bytes via malloc() section .data ptr_storage dq 0 ; Qword to store the malloc'd pointer (64-bit) section .text extern malloc extern free global main main: ; Ensure stack is 16-byte aligned (adjust if you pushed registers earlier) sub rsp, 8 ; If main was called with rsp aligned, this adjusts to maintain alignment for calls ; Call malloc(8000) mov rdi, 8000 ; First argument: number of bytes to allocate call malloc ; Check for allocation failure (rax == NULL) test rax, rax jz malloc_failed ; Handle error if needed ; Save the pointer for later use/free mov [ptr_storage], rax ; --- Use the allocated memory here --- ; Example: Write a byte to the start of the block mov byte [rax], 0x41
Correct free() Implementation
Now for the part you're unsure about—freeing the memory is straightforward once you follow the calling convention:
; --- Free the allocated memory --- mov rdi, [ptr_storage] ; Load the saved malloc'd pointer into rdi (first argument for free) call free ; Call free()—no return value to check ; Optional: Null out the pointer to avoid wild pointers later mov qword [ptr_storage], 0 malloc_failed: ; Clean up stack and exit add rsp, 8 mov rax, 1 ; Exit syscall number (64-bit) mov rdi, 1 ; Exit code 1 (error) syscall
Critical Notes to Avoid Bugs
- Only pass the exact pointer from
malloc: Never pass a pointer that points to the middle of the allocated block, or a pointer that wasn't returned bymalloc/calloc/realloc—this causes undefined behavior (crashes, memory corruption). - Stack alignment is non-negotiable: If your code pushes registers before calling
mallocorfree, calculate how many bytes you've pushed (each push is 8 bytes in 64-bit) and adjustrspso it's divisible by 16 right before thecallinstruction. - Link correctly: When assembling and linking, make sure you link against the C standard library. For example:
nasm -f elf64 your_program.asm -o your_program.o gcc your_program.o -o your_program # gcc automatically links libc # Or manually with ld: # ld your_program.o -o your_program -lc -dynamic-linker /lib64/ld-linux-x86-64.so.2 - Freeing NULL is safe: If
mallocfailed (returned NULL), callingfree(NULL)won't cause issues—this is explicitly allowed by the C standard.
内容的提问来源于stack exchange,提问作者RTC222

