Können wir überprüfen, ob ein an eine Funktion übergebener Zeiger in C mit Speicher belegt ist oder nicht?
Ich habe meine eigene Funktion in C geschrieben, die einen Zeichenzeiger - buf [Zeiger auf einen Puffer] und size - buf_siz [Puffergröße] akzeptiert . Tatsächlich muss der Benutzer vor dem Aufrufen dieser Funktion einen Puffer erstellen und ihm den Speicher von buf_siz zuweisen.
Da die Möglichkeit besteht, dass der Benutzer die Speicherzuweisung vergisst und einfach den Zeiger auf meine Funktion übergibt, möchte ich dies überprüfen. Gibt es also eine Möglichkeit, meine Funktion zu überprüfen, um festzustellen, ob der übergebene Zeiger wirklich mit der Speichermenge von buf_siz belegt ist?
EDIT1: Es scheint, dass es keine Standardbibliothek gibt, um es zu überprüfen. Aber gibt es einen schmutzigen Hack, um es zu überprüfen?
EDIT2: Ich weiß, dass meine Funktion von einem guten C-Programmierer verwendet wird ... Aber ich möchte wissen, ob wir prüfen können oder nicht. Wenn wir können, würde ich gerne davon hören.
Schlussfolgerung: Es ist daher unmöglich zu überprüfen, ob einem bestimmten Zeiger ein Speicher zugewiesen ist oder nicht
Antworten:
Sie können nur einige implementierungsspezifische Hacks überprüfen.
Zeiger haben keine anderen Informationen als die, auf die sie zeigen. Das Beste, was Sie tun können, ist zu sagen: "Ich weiß, wie diese bestimmte Compiler-Version Speicher zuweist, also werde ich den Speicher dereferenzieren, den Zeiger um 4 Bytes zurückbewegen, die Größe überprüfen, sicherstellen, dass er übereinstimmt ..." und so weiter. Sie können dies nicht auf standardmäßige Weise tun, da die Speicherzuweisung für die Implementierung definiert ist. Ganz zu schweigen davon, dass sie es möglicherweise überhaupt nicht dynamisch zugewiesen haben.
Sie müssen nur davon ausgehen, dass Ihr Client weiß, wie man in C programmiert. Die einzige Lösung, die ich mir vorstellen kann, besteht darin, den Speicher selbst zuzuweisen und zurückzugeben, aber das ist kaum eine kleine Änderung. (Es ist eine größere Designänderung.)
quelle
malloc
der einenNULL
Zeiger zurückgibt, wenn er keinen Speicher zuordnen konnte. Also ... daraufmalloc
vertrauen wir?Der folgende Code wurde einmal verwendet, um zu überprüfen, ob ein Zeiger versucht, auf illegalen Speicher zuzugreifen. Der Mechanismus besteht darin, ein SIGSEGV zu induzieren. Das SEGV-Signal wurde früher zu einer privaten Funktion umgeleitet, die longjmp verwendet, um zum Programm zurückzukehren. Es ist eine Art Hack, aber es funktioniert.
Der Code kann verbessert werden (verwenden Sie 'Sigaction' anstelle von 'Signal' usw.), aber es ist nur eine Idee. Es ist auch auf andere Unix-Versionen portierbar, für Windows bin ich mir nicht sicher. Beachten Sie, dass das SIGSEGV-Signal nicht an einer anderen Stelle in Ihrem Programm verwendet werden sollte.
#include <stdio.h> #include <stdlib.h> #include <setjmp.h> #include <signal.h> jmp_buf jump; void segv (int sig) { longjmp (jump, 1); } int memcheck (void *x) { volatile char c; int illegal = 0; signal (SIGSEGV, segv); if (!setjmp (jump)) c = *(char *) (x); else illegal = 1; signal (SIGSEGV, SIG_DFL); return (illegal); } int main (int argc, char *argv[]) { int *i, *j; i = malloc (1); if (memcheck (i)) printf ("i points to illegal memory\n"); if (memcheck (j)) printf ("j points to illegal memory\n"); free (i); return (0); }
quelle
i = malloc(1);
ist ein gültiger C-Code und vorzuzieheni = (int*) malloc(1);
. Vielleicht denken Sie an eine andere Sprache.setjmp()
undlongjmp()
sollte wahrscheinlich durchsigsetjmp()
und ersetzt werdensiglongjmp()
. Siehe stackoverflow.com/questions/20755260/…c = *(char *)(x);
könnten gut durchgehen , obwohl Siex
nicht auf einen zugewiesenen Bereich verweisen.SEGV
Wird nur ausgelöst, wenn der Zeiger innerhalb eines Speichersegments zeigt, auf das nicht zugegriffen werden kann, die Segmente jedoch mehrere KB groß sind. Wenn Sie also 4 Bytes zuweisen10
, ändert sich die Mem-Adresse20
trotz außerhalb eines zugewiesenen Bereichs immer noch im selben Segment Als Adresse10
, daher ohne Zuweisung, können Sie dennoch20
ohne SEGV auf die Adresse zugreifen.NULL
, denn dieser Wert ist , garantiert eine SEGV verursachen , wenn Sie versuchen , es zu dereferenzieren ... Es ist nicht für andere Speicheradresse garantiert.Für eine plattformspezifische Lösung interessieren Sie möglicherweise die Win32-Funktion
IsBadReadPtr
(und andere, die sie mögen). Diese Funktion kann (fast) vorhersagen, ob beim Lesen aus einem bestimmten Speicherblock ein Segmentierungsfehler auftritt.Dies schließt jedoch nicht schützt Sie im allgemeinen Fall, da das Betriebssystem nichts von dem C - Laufzeit - Heap - Manager kennt, und wenn ein Anrufer Stiche in einem Puffer, der nicht so groß ist wie Sie erwarten, dann den Rest der Heap - Blöcke wird aus Sicht des Betriebssystems weiterhin lesbar sein.
quelle
Ich initialisiere Zeiger immer auf Null. Wenn ich Speicher reserviere, ändert sich dies. Wenn ich überprüfe, ob Speicher zugewiesen wurde, tue ich das
pointer != NULL
. Wenn ich Speicher freigebe, setze ich auch den Zeiger auf null. Ich kann mir keine Möglichkeit vorstellen, festzustellen, ob genügend Speicher zugewiesen wurde.Dies löst Ihr Problem nicht, aber Sie müssen darauf vertrauen, dass jemand, der C-Programme schreibt, geschickt genug ist, um es richtig zu machen.
quelle
Ich habe einmal einen Dirty Hack auf meinem 64-Bit-Solaris verwendet. Im 64-Bit-Modus beginnt der Heap bei 0x1 0000 0000. Durch Vergleichen des Zeigers konnte ich feststellen, ob es sich um einen Zeiger im Daten- oder Codesegment
p < (void*)0x100000000
, einen Zeiger im Heapp > (void*)0x100000000
oder einen Zeiger in einem Speicherbereich handelt(intptr_t)p < 0
(mmap gibt Adressen von oben zurück des adressierbaren Bereichs). Dies ermöglichte es meinem Programm, zugewiesene und speicherabgebildete Zeiger in derselben Karte zu halten und mein Kartenmodul die richtigen Zeiger freizugeben.Diese Art von Trick ist jedoch höchst unportabel. Wenn Ihr Code auf so etwas basiert, ist es an der Zeit, die Architektur Ihres Codes zu überdenken. Du machst wahrscheinlich etwas falsch.
quelle
Nein, im Allgemeinen gibt es keine Möglichkeit, dies zu tun.
Wenn Ihre Schnittstelle nur "einen Zeiger auf einen Puffer übergeben, in den ich etwas einfügen werde", kann der Anrufer außerdem festlegen, dass überhaupt kein Speicher zugewiesen wird, und stattdessen einen statisch zugewiesenen Puffer fester Größe oder eine automatische Variable oder etwas anderes verwenden. Oder vielleicht ist es ein Zeiger auf einen Teil eines größeren Objekts auf dem Heap.
Wenn Ihre Schnittstelle ausdrücklich sagt "Übergeben Sie einen Zeiger auf den zugewiesenen Speicher (weil ich ihn freigeben werde)", sollten Sie damit rechnen, dass der Anrufer dies tut. Andernfalls können Sie dies nicht zuverlässig erkennen.
quelle
valgrind
;) verwendenEin Hack, den Sie versuchen können, besteht darin, zu überprüfen, ob Ihr Zeiger auf den zugewiesenen Speicher zeigt. Dies hilft Ihnen im Allgemeinen nicht weiter, da der zugewiesene Puffer möglicherweise zu klein ist oder der Zeiger auf einen globalen Speicherabschnitt (.bss, .const, ...) zeigt.
Um diesen Hack auszuführen, speichern Sie zuerst die Adresse der ersten Variablen in main (). Später können Sie diese Adresse mit der Adresse einer lokalen Variablen in Ihrer spezifischen Routine vergleichen. Alle Adressen zwischen beiden Adressen befinden sich auf dem Stapel.
quelle
char copy[255] = {0}; snprintf(copy, sizeof(copy), "%n: %s\n", error_code, error_msg); copy[sizeof(copy) -1] = 0; write(log_fd, copy, strnlen(copy) + 1); copy[0] = 0;
wennsnprintf
seltsame Überprüfungen, wie Sie vorgeschlagen haben,snprintf
fälschlicherweise alscopy
ungültiger Zeiger angesehen würden ...Ich weiß , dass dies eine alte Frage, aber fast alles ist möglich in C. ein paar hackish Lösungen hier schon gibt es aber eine gültige Art und Weise zu bestimmen , ob Speicher richtig zugeordnet worden ist , ein Orakel zu verwenden , um den Platz zu nehmen
malloc
,calloc
,realloc
, undfree
. Auf diese Weise können Test-Frameworks (wie z. B. cmocka) Speicherprobleme erkennen (Seg-Fehler, Speicherfreigabe usw.). Sie können eine Liste der zugewiesenen Speicheradressen verwalten, während diese zugewiesen werden, und diese Liste einfach überprüfen, wenn der Benutzer Ihre Funktion verwenden möchte. Ich habe etwas sehr Ähnliches für mein eigenes Test-Framework implementiert. Ein Beispielcode:typedef struct memory_ref { void *ptr; int bytes; memory_ref *next; } memory_ref *HEAD = NULL; void *__wrap_malloc(size_t bytes) { if(HEAD == NULL) { HEAD = __real_malloc(sizeof(memory_ref)); } void *tmpPtr = __real_malloc(bytes); memory_ref *previousRef = HEAD; memory_ref *currentRef = HEAD->next; while(current != NULL) { previousRef = currentRef; currentRef = currentRef->next; } memory_ref *newRef = (memory_ref *)__real_malloc(sizeof(memory_ref)); *newRef = (memory_ref){ .ptr = tmpPtr, .bytes = bytes, .next = NULL }; previousRef->next = newRef; return tmpPtr; }
Sie müßten ähnliche Funktionen für
calloc
,realloc
undfree
, jede Wrapper mit dem Präfix__wrap_
. Der Realmalloc
ist über die Verwendung von verfügbar__real_malloc
(ähnlich für die anderen Funktionen, die Sie einschließen). Wenn Sie überprüfen möchten, ob tatsächlich Speicher zugewiesen ist, durchlaufen Sie einfach die verknüpftememory_ref
Liste und suchen Sie nach der Speicheradresse. Wenn Sie es finden und es groß genug ist, wissen Sie mit Sicherheit, dass die Speicheradresse Ihr Programm nicht zum Absturz bringt. Andernfalls geben Sie einen Fehler zurück. In der Header-Datei, die Ihr Programm verwendet, würden Sie folgende Zeilen hinzufügen:extern void *__real_malloc (size_t); extern void *__wrap_malloc (size_t); extern void *__real_realloc (size_t); extern void *__wrap_realloc (size_t); // Declare all the other functions that will be wrapped...
Meine Anforderungen waren ziemlich einfach, daher habe ich eine sehr grundlegende Implementierung implementiert. Sie können sich jedoch vorstellen, wie diese erweitert werden könnte, um ein besseres Tracking-System zu erhalten (z. B. ein System zu erstellen
struct
, das zusätzlich zur Größe den Speicherort verfolgt). Dann kompilieren Sie einfach den Code mitgcc src_files -o dest_file -Wl,-wrap,malloc -Wl,-wrap,calloc -Wl,-wrap,realloc -Wl,-wrap,free
Der Nachteil ist, dass der Benutzer seinen Quellcode mit den oben genannten Anweisungen kompilieren muss. Es ist jedoch alles andere als das Schlimmste, das ich gesehen habe. Das Zuweisen und Freigeben von Speicher ist mit einem gewissen Aufwand verbunden, beim Hinzufügen von Sicherheit jedoch immer mit einem gewissen Aufwand.
quelle
Ich kenne keine Möglichkeit, dies aus einem Bibliotheksaufruf heraus zu tun, aber unter Linux können Sie sich das ansehen
/proc/<pid>/numa_maps
. Es werden alle Speicherbereiche angezeigt und in der dritten Spalte wird "Heap" oder "Stack" angezeigt. Sie können sich den Rohzeigerwert ansehen, um zu sehen, wo er ausgerichtet ist.Beispiel:
00400000 prefer:0 file=/usr/bin/bash mapped=163 mapmax=9 N0=3 N1=160 006dc000 prefer:0 file=/usr/bin/bash anon=1 dirty=1 N0=1 006dd000 prefer:0 file=/usr/bin/bash anon=9 dirty=9 N0=3 N1=6 006e6000 prefer:0 anon=6 dirty=6 N0=2 N1=4 01167000 prefer:0 heap anon=122 dirty=122 N0=25 N1=97 7f39904d2000 prefer:0 anon=1 dirty=1 N0=1 7f39904d3000 prefer:0 file=/usr/lib64/ld-2.17.so anon=1 dirty=1 N0=1 7f39904d4000 prefer:0 file=/usr/lib64/ld-2.17.so anon=1 dirty=1 N1=1 7f39904d5000 prefer:0 anon=1 dirty=1 N0=1 7fffc2d6a000 prefer:0 stack anon=6 dirty=6 N0=3 N1=3 7fffc2dfe000 prefer:0
Zeiger, die über 0x01167000, aber unter 0x7f39904d2000 liegen, befinden sich im Heap.
quelle
Sie können nichts überprüfen, was in Standard C verfügbar ist. Selbst wenn Ihr spezifischer Compiler eine Funktion dafür bereitstellen würde, wäre dies immer noch eine schlechte Idee. Hier ist ein Beispiel dafür, warum:
int YourFunc(char * buf, int buf_size); char str[COUNT]; result = YourFunc(str, COUNT);
quelle
Wie alle anderen sagten, gibt es keinen Standardweg.
Bisher hat noch niemand ' Writing Solid Code ' von Steve Maguire erwähnt. Obwohl in einigen geißelte Viertel , hat das Buchkapitel zum Thema Speicherverwaltung und erläutert , wie mit Sorgfalt und die vollständige Kontrolle über alle Speicherzuweisung im Programm, können Sie tun , wie Sie fragen , und bestimmen , ob ein Zeiger Sie gegeben sind a gültiger Zeiger auf dynamisch zugewiesenen Speicher. Wenn Sie jedoch Bibliotheken von Drittanbietern verwenden möchten, werden Sie feststellen, dass nur wenige von ihnen es Ihnen ermöglichen, die Speicherzuweisungsroutinen in Ihre eigenen zu ändern, was eine solche Analyse erheblich erschwert.
quelle
Im Allgemeinen sind lib-Benutzer für die Eingabeprüfung und -verifizierung verantwortlich. Möglicherweise sehen Sie ASSERT oder etwas im lib-Code und sie werden nur für Debug-Zwecke verwendet. Dies ist eine Standardmethode beim Schreiben von C / C ++. während so viele Programmierer solche Überprüfungen und Verifizierungen in ihrem Lib-Code sehr sorgfältig durchführen möchten. wirklich "schlechte" Gewohnheiten. Wie in IOP / IOD angegeben, sollten lib-Schnittstellen die Verträge sein und klar machen, was die lib tun wird und was nicht, was ein lib-Benutzer tun sollte und was nicht notwendig sein sollte.
quelle
Es gibt einen einfachen Weg, dies zu tun. Wenn Sie einen Zeiger erstellen, schreiben Sie einen Wrapper darum. Zum Beispiel, wenn Ihr Programmierer Ihre Bibliothek verwendet, um eine Struktur zu erstellen.
struct struct_type struct_var;
Stellen Sie sicher, dass er Speicher mit Ihrer Funktion wie z
struct struct_type struct_var = init_struct_type()
Wenn diese struct_var Speicher enthält, der dynamisch zugewiesen wird, z.
wenn die Definition von struct_type war
typedef struct struct_type { char *string; }struct_type;
Führen Sie dann in Ihrer Funktion init_struct_type () Folgendes aus:
init_struct_type() { struct struct_type *temp = (struct struct_type*)malloc(sizeof(struct_type)); temp->string = NULL; return temp; }
Auf diese Weise bleibt er NULL, es sei denn, er weist einem Wert die temporäre Zeichenfolge zu. Sie können in den Funktionen, die diese Struktur verwenden, einchecken, ob die Zeichenfolge NULL ist oder nicht.
Eine weitere Sache, wenn der Programmierer so schlecht ist, dass er Ihre Funktionen nicht verwendet, sondern direkt auf nicht zugewiesenen Speicher zugreift, hat er es nicht verdient, Ihre Bibliothek zu verwenden. Stellen Sie einfach sicher, dass Ihre Dokumentation alles spezifiziert.
quelle
Nun, ich weiß nicht, ob jemand es nicht schon hier platziert hat oder ob es eine Möglichkeit in Ihrem Programm sein wird. Ich hatte in meinem Universitätsprojekt mit ähnlichen Dingen zu kämpfen.
Ich habe es ganz einfach gelöst - Im Initialisierungsteil von main () habe
LIST *ptr
ich das einfach gesagt , nachdem ich es deklariert habeptr=NULL
. So was -int main(int argc, char **argv) { LIST *ptr; ptr=NULL;
Wenn die Zuordnung fehlschlägt oder Ihr Zeiger überhaupt nicht zugewiesen wird, ist er NULL. SO können Sie es einfach mit if testen.
if (ptr==NULL) { "THE LIST DOESN'T EXIST" } else { "THE LIST MUST EXIST --> SO IT HAS BEEN ALLOCATED" }
Ich weiß nicht, wie Ihr Programm geschrieben ist, aber Sie verstehen sicherlich, worauf ich hinweisen möchte. Wenn es möglich ist, Ihre Zuordnung auf diese Weise zu überprüfen und dann Ihre Argumente an Ihre Funktion zu übergeben, könnten Sie eine einfache Lösung haben.
Natürlich müssen Sie darauf achten, dass Ihre Funktionen beim Zuweisen und Erstellen der Struktur gut ausgeführt werden, aber wo in C müssen Sie nicht vorsichtig sein.
quelle
Nein, das kannst du nicht. Sie werden feststellen, dass dies in der Standardbibliothek oder anderswo nicht funktioniert. Das liegt daran, dass es keine Standardmethode gibt. Der aufrufende Code muss nur die Verantwortung für die korrekte Verwaltung des Speichers übernehmen.
quelle
Ein nicht initialisierter Zeiger ist genau das - nicht initialisiert. Es kann auf irgendetwas verweisen oder einfach eine ungültige Adresse sein (dh eine, die nicht dem physischen oder virtuellen Speicher zugeordnet ist).
Eine praktische Lösung besteht darin, eine Gültigkeitsunterschrift in den Objekten zu haben, auf die verwiesen wird. Erstellen Sie einen malloc () - Wrapper, der die angeforderte Blockgröße plus die Größe einer Signaturstruktur zuweist, eine Signaturstruktur am Anfang des Blocks erstellt, aber den Zeiger auf die Position nach der Signatur zurückgibt. Sie können dann eine Validierungsfunktion erstellen, die den Zeiger verwendet, einen negativen Offset verwendet, um die Gültigkeitsstruktur abzurufen und zu überprüfen. Sie benötigen natürlich einen entsprechenden free () - Wrapper, um den Block durch Überschreiben der Gültigkeitssignatur ungültig zu machen und das Free ab dem tatsächlichen Start des zugewiesenen Blocks auszuführen.
Als Gültigkeitsstruktur können Sie die Größe des Blocks und dessen Ergänzung verwenden. Auf diese Weise können Sie nicht nur den Block validieren (XOR die beiden Werte und mit Null vergleichen), sondern auch Informationen zur Blockgröße erhalten.
quelle
Ein Zeiger-Tracker verfolgt und überprüft die Gültigkeit eines Zeigers
Verwendung:
Speicher erstellen int * ptr = malloc (sizeof (int) * 10);
Fügen Sie die Zeigeradresse zum Tracker hinzu. Ptr (& ptr);
auf fehlerhafte Zeiger prüfen PtrCheck ();
und geben Sie alle Tracker am Ende Ihres Codes frei
PtrFree ();
#include <stdlib.h> #include <string.h> #include <stdio.h> #include <stdint.h> #include <stdbool.h> struct my_ptr_t { void ** ptr; size_t mem; struct my_ptr_t *next, *previous; }; static struct my_ptr_t * ptr = NULL; void Ptr(void * p){ struct my_ptr_t * tmp = (struct my_ptr_t*) malloc(sizeof(struct my_ptr_t)); printf("\t\tcreating Ptr tracker:"); if(ptr){ ptr->next = tmp; } tmp->previous = ptr; ptr = tmp; ptr->ptr = p; ptr->mem = **(size_t**) ptr->ptr; ptr->next = NULL; printf("%I64x\n", ptr); }; void PtrFree(void){ if(!ptr){ return; } /* if ptr->previous == NULL */ if(!ptr->previous){ if(*ptr->ptr){ free(ptr->ptr); ptr->ptr = NULL; } free(ptr); ptr = NULL; return; } struct my_ptr_t * tmp = ptr; for(;tmp != NULL; tmp = tmp->previous ){ if(*tmp->ptr){ if(**(size_t**)tmp->ptr == tmp->mem){ free(*tmp->ptr); *tmp->ptr = NULL; } } free(tmp); } return; }; void PtrCheck(void){ if(!ptr){ return; } if(!ptr->previous){ if(*(size_t*)ptr->ptr){ if(*ptr->ptr){ if(**(size_t**) ptr->ptr != ptr->mem){ printf("\tpointer %I64x points not to a valid memory address", ptr->mem); printf(" did you freed the memory and not NULL'ed the pointer or used arthmetric's on pointer %I64x?\n", *ptr->ptr); return; } } return; } return; } struct my_ptr_t * tmp = ptr; for(;tmp->previous != NULL; tmp = tmp->previous){ if(*(size_t*)tmp->ptr){ if(*tmp->ptr){ if(**(size_t**) tmp->ptr != tmp->mem){ printf("\tpointer %I64x points not to a valid memory address", tmp->mem); printf(" did you freed the memory and not NULL'ed the pointer or used arthmetric's on pointer %I64x?\n", *tmp->ptr); continue; } } continue; } } return; }; int main(void){ printf("\n\n\t *************** Test ******************** \n\n"); size_t i = 0; printf("\t *************** create tracker ********************\n"); int * ptr = malloc(sizeof(int) * 10); Ptr(&ptr); printf("\t *************** check tracker ********************\n"); PtrCheck(); printf("\t *************** free pointer ********************\n"); free(ptr); printf("\t *************** check tracker ********************\n"); PtrCheck(); printf("\t *************** set pointer NULL *******************\n"); ptr = NULL; printf("\t *************** check tracker ********************\n"); PtrCheck(); printf("\t *************** free tracker ********************\n"); PtrFree(); printf("\n\n\t *************** single check done *********** \n\n"); printf("\n\n\t *************** start multiple test *********** \n"); int * ptrs[10]; printf("\t *************** create trackers ********************\n"); for(; i < 10; i++){ ptrs[i] = malloc(sizeof(int) * 10 * i); Ptr(&ptrs[i]); } printf("\t *************** check trackers ********************\n"); PtrCheck(); printf("\t *************** free pointers but set not NULL *****\n"); for(i--; i > 0; i-- ){ free(ptrs[i]); } printf("\t *************** check trackers ********************\n"); PtrCheck(); printf("\t *************** set pointers NULL *****************\n"); for(i=0; i < 10; i++){ ptrs[i] = NULL; } printf("\t *************** check trackers ********************\n"); PtrCheck(); printf("\t *************** free trackers ********************\n"); PtrFree(); printf("\tdone"); return 0; }
quelle
Es gibt fast nie "nie" in Computern. Plattformübergreifend ist weit über den Erwartungen. Nach 25 Jahren habe ich an Hunderten von Projekten gearbeitet, die alle plattformübergreifend waren, und es kam nie zustande.
Offensichtlich würde eine Variable auf dem Stapel auf einen Bereich auf dem Stapel zeigen, der fast linear ist. Plattformübergreifende Garbage Collectors markieren die Oberseite oder (Unterseite) des Stapels, rufen eine kleine Funktion auf, um zu überprüfen, ob der Stapel nach oben oder unten wächst, und überprüfen dann den Stapelzeiger, um festzustellen, wie groß der Stapel ist. Dies ist Ihre Reichweite. Ich kenne keine Maschine, die keinen Stack auf diese Weise implementiert (entweder beim Aufwachsen oder beim Aufwachsen).
Sie überprüfen einfach, ob sich die Adresse unseres Objekts oder Zeigers zwischen dem oberen und unteren Rand des Stapels befindet. So würden Sie wissen, ob es sich um eine Stapelvariable handelt.
Zu einfach. Hey, ist es richtig c ++? Ist richtig wichtig? In 25 Jahren habe ich viel mehr Einschätzung der Richtigkeit gesehen. Sagen wir es so: Wenn Sie hacken, programmieren Sie nicht wirklich, sondern regurigieren wahrscheinlich nur etwas, was bereits getan wurde.
Wie interessant ist das
quelle
malloc
-ähnliche Funktionen nicht unbedingt eine Aktion aus, die zur Heap-Erweiterung führt. C ++ hat eine völlig neue Art der Speicherzuweisung und jeder weiß, dass die Verwendung der vordefinierten Funktionen von C keine gute Idee ist.