Hallo!
Moin!
Ich versuche mir gerade C etwas näher zu bringen anhand des Galileo Openbooks "C von A bis Z". Beim aktuellen Kapitel (http://www.galileocomputing.de/openbook/c_von_a_bis_z/c_014_005.htm#RxxobKap014005040028BF1F0331A3) habe ich nun jedoch mal eine Frage:
Warum funktioniert das Programm:
#include <stdio.h>
#include <string.h>char *myfunc(void) {
char *output = "Output";
//strcat(output, arg);
return output;
}
; Das Kompilat dazu sieht so aus:
4: char *myfunc(void) {
00401020 push ebp
00401021 mov ebp,esp
00401023 push ecx
; Hier
5: char *output = "Output";
00401024 mov dword ptr [output],offset ___xt_z(0x00410a30)+10Ch
; wird nichts alloziert, sondern an die (Stack) Variable die Adresse einer
; Zeichenkette, irgendwo "fest" im Speicher liegt, zugewiesen
6: //strcat(output, arg);
; Hier
7: return output;
0040102B mov eax,dword ptr [output]
; wird dann der WERT der Variablen nach EAX gerettet,
8: }
0040102E mov esp,ebp
; und ier wird dann lediglich der Stackrahmen freigegeben,
; die Stack-VARIABLE "output" ist danach ungültig; aber
; ihr ehemaliger WERT ist immer noch eine gültige feste Speicheradresse
; die später weiterverwandt wird
00401030 pop ebp
00401031 ret
9:
In dem Registerdump
EAX = 00420250 EBX = 7FFDF000
ECX = 00000001 EDX = 004202D0
ESI = 02ADF80C EDI = 7C9100E0
EIP = 00401024 ESP = 0012FF6C
EBP = 0012FF70 EFL = 00000216
CS = 001B DS = 0023 ES = 0023
SS = 0023 FS = 003B GS = 0000 OV=0
UP=0 EI=1 PL=0 ZR=0 AC=1 PE=1 CY=0
dazu kannst Du sehen, dass SS(STACK), ES(HEAP) und DS(DATA) alle die gleichen Selektoren haben; deshalb werden hier nur kurze Offset-Zeiger benutzt.
Wenn Du dir mal einen Hexdump Deines Programms anschaust, wirst Du darin auch die - feste - Zeichenkette "Output" entdecken; der UNIX-Befehl "strings" zeigt sie Dir auch an.
Allerdings ändert das nichts an der Grundregel, dass man Adressen lokal allozierter Variablen nicht zurückgeben darf; hier geht es zwar mal, aber guter Stil wäre sowas nicht.
Grüsse
Solkar