全局静态uint64_t数组运行时地址变更原因及解决方法问询
Let's break down why your static uint64_t arr[] shows a different address at runtime compared to the linker's assigned value, even after you disabled ASLR.
Key Cause: Position-Independent Executable (PIE) Compilation
The most likely culprit here is that your binary is being compiled as a Position-Independent Executable (PIE). Modern GCC/clang defaults to enabling PIE for security purposes, even if you don't explicitly specify it. Here's how this leads to the address shift:
- When compiling with PIE, the linker assigns relative virtual addresses (offsets from a base load address) instead of fixed absolute addresses.
- Even with ASLR disabled (
sudo bash -c 'echo 0 > /proc/sys/kernel/randomize_va_space'), PIE binaries load at a fixed default base address (typically0x555555554000on x86_64 systems). - Your linker-assigned address
0x201060is the offset from this base. Adding them together:0x555555554000 + 0x201060 = 0x555555755060—which exactly matches the runtime address you observed in GDB.
In contrast, your precompiled binary was likely built with the -no-pie flag, generating a traditional non-PIE executable. These binaries load at the exact absolute address the linker specifies, so no address shift occurs.
How to Verify This
To confirm PIE is the issue:
- Check your binary type with this command:
If the output includes "Position-Independent Executable", PIE is enabled.file a.out - Or inspect the ELF header with
readelf:
Look for thereadelf -h a.outTypefield—DYNmeans it's a PIE binary, whileEXECindicates a non-PIE executable.
Fix: Disable PIE During Compilation
Add the -no-pie flag to your compile command to generate a non-PIE executable, which will use the linker's absolute address at runtime:
gcc -g -fno-stack-protector -z execstack -no-pie test.c -o a.out
After recompiling, when you debug in GDB:
- The static view (
x/x arrbefore running the program) and runtime view (x/x arrafter hitting the breakpoint) will show the same address:0x201060.
Additional Notes
- Disabling ASLR only prevents randomization of the load address—it doesn't remove PIE's base address offset. PIE and ASLR are separate features: PIE enables loading at any address, while ASLR chooses that address randomly.
- The
staticqualifier on your array only restricts its visibility to the current translation unit; it doesn't affect its memory layout or load address.
内容的提问来源于stack exchange,提问作者James Houghton

