Ja det stämmer. Nyckelorden är "som kompilatorn inte känner till".
Den behöver inte veta hur implementeringen av memset ser ut eller att funktionen länkas in externt. Den vet vad resultatet ska bli och att det inte finns några okända bieffekter eftersom memsets beteende är spec:at i standarden.
Om du skriver en funktion som ska mata hunden och döper den till memset har du ingen rätt att klaga när hunden svälter ihjäl eftersom du använde ett reserverat namn och kompilatorn tog bort vad den trodde var ett känt beteende.
The names of all library types, macros, variables and functions that come from the ISO C standard are reserved unconditionally; your program may not redefine these names.
Visst, det är ganska vanligt att folk gör sina egna implementationer med standardnamn ändå, och det fungerar oftast. Men det är inte garanterat att fungera.
Jag hade däremot fel om volatile, gcc tar bort memset ändå.
Kod: Markera allt
extern void foo(void*);
int main() {
volatile char* p = malloc(10*sizeof(*p));
foo(p);
memset(p, 0, 10*sizeof(*p));
free(p);
}
Kompilerat med O2, register-accesser borttagna för att spara plats.
Sätter man memset före foo-anropet får gcc inte ta bort memset eftersom det påverkar minnet som foo ser.
Kod: Markera allt
main:
call calloc <-- malloc utbytt. gcc ser inte koden för malloc & calloc internt men den vet vad resultatet ska bli
call foo
call free
Det verkar som att det enda sättet att garantera att memset blir kvar i gcc är att stänga av optimeringen, antingen globalt eller i en wrapper-funktion.
Kod: Markera allt
__attribute__((optimize("no-dce"))) // no dead code elimination
__attribute__((noinline))
void* mymemset(void *s, int c, size_t n) {
return memset(s, c, n);
}
Kod: Markera allt
main:
call malloc
call foo
call mymemset
call free
mymemset:
jmp memset
memset på globaler eller statics kommer inte tas bort. Detta gäller bara dynamiskt allokerat minne och stack-variabler.