https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69271
--- Comment #6 from nsz at gcc dot gnu.org --- to complete the example here is a test application: #include <stdio.h> #include <stdlib.h> extern char **environ; int main() { printf("&environ: %p, environ: %p, *environ: %p\n", &environ, environ, *environ); clearenv(); // *environ = 0 putenv("TEST=1"); // should change environ printf("&environ: %p, environ: %p, *environ: %p\n", &environ, environ, *environ); } with correct libc.so: $ gcc a.c $ ./a.out &environ: 0x6008b0, environ: 0x7fffb9b0b478, *environ: 0x7fffb9b0d651 &environ: 0x6008b0, environ: 0x600020, *environ: 0x400649 $ readelf --dyn-sym -W ./a.out |grep envi 2: 00000000006008b0 8 OBJECT WEAK DEFAULT 19 _environ 5: 00000000006008b0 8 OBJECT GLOBAL DEFAULT 19 __environ 7: 00000000006008b0 8 OBJECT WEAK DEFAULT 19 environ 8: 00000000006008b0 8 OBJECT WEAK DEFAULT 19 ___environ if libc.so is compiled with -flto: $ gcc a.c $ ./a.out &environ: 0x600850, environ: 0x7fff52af6158, *environ: 0x7fff52af6651 &environ: 0x600850, environ: 0x7fff52af6158, *environ: 0 $ readelf --dyn-sym -W ./a.out |grep envi 5: 0000000000600850 8 OBJECT GLOBAL DEFAULT 19 environ so environ is shared between a.out and libc.so in the beginning (clearenv worked), but the address of the symbol (&environ) is different so changing it in the libc did not have an effect in the main module (putenv failed). this might be an issue in the static or dynamic linker but the difference is observable.