2010-11-22 7 views
1

gcc 4.4.5 c89befreiend zugewiesenen Speicher

Ich habe eine Funktion namens create_object, wo ich Speicher für eine globale Struktur zuordnen. Und ich habe eine Funktion namens destroy_object, wo ich überprüfe, dass der Zeiger nicht null ist, dann bin ich frei. Nur wenn ich Speicher freistelle, der nicht zugewiesen wurde. Ich habe dies jedoch getestet, indem ich 2 aufeinanderfolgende Aufrufe von destroy_object gemacht habe. Allerdings bekomme ich beim zweiten Aufruf einen Stack-Dump. Ich bin mir aber sicher, dass es nicht frei wird, da ich den Zeiger auf NULL zugewiesen habe. Also sollte die freie Funktion übersprungen werden.

static struct Config_t { 
    char protocol[LINE_SIZE]; 
    char mode[LINE_SIZE]; 
} *app_cfg = NULL; 

int create_object() 
{ 
    app_cfg = malloc(sizeof *app_cfg); 
    memset(app_cfg, 0, sizeof *app_cfg); 
} 

void destroy_config() 
{ 
    /* Check to see if the memory is ok to free */ 
    if(app_cfg != NULL) { 
     free(app_cfg); 
     app_cfg = NULL; 
    } 
} 

Vielen Dank für Ihre Anregungen,

================= EDIT ========== Basicially Ich habe in Meine Hauptfunktion ist ein Aufruf von create_object() und ich mache eine Bearbeitung und dann einen Aufruf von destory_object.

int main(void) 
{ 
    create_object(); 

    /* Do some processing on the structure */ 

    destroy_object(); 

    return 0; 
} 

========================= Finale bearbeiten ==== static struct Config_t { char-Protokoll [LINE_SIZE]; Zeichenmodus [LINE_SIZE]; } app_cfg [1] {{"", ""}};

Und jetzt benutze ich nicht malloc und frei.

+1

Das sieht gut aus, können Sie den Code, der diesen Zeiger verwendet, und Aufrufe an 'create_object' und' destroy_config' posten? Wenn Sie Ihren Speicher, der 'app_cfg' zugewiesen ist, sofort auf 0s initialisieren möchten, können Sie auch Ihre' malloc'- und memset'-Aufrufe zu einem 'Calloc'-Aufruf kombinieren. Auch "free" auf einen Nullzeiger ist völlig in Ordnung. – birryree

+1

Das Übergeben eines Null-Zeigers an 'free()' ist ein sicheres No-Op, so dass Sie in 'destroy_config()' nicht die Null-Überprüfung benötigen. – Wyzard

+2

können Sie den Code über gdb ausführen und das Backtrace nach dem SIGSEGV anzeigen? Zeigt es auf einen anderen Ort in Ihrem Programm? – vpit3833

Antwort

3

Ich habe nur einen Vorschlag. Reservieren Sie keine Speicher dafür, es ist eine Verschwendung von Aufwand.

Da app_cfg eine Variable auf Dateiebene ist, können Sie sowieso nur eine Kopie auf einmal haben, daher ist es wenig sinnvoll, sie zuzuordnen und zu entfernen.

Erstellen Sie einfach es als statischer Nicht-Zeiger und verwende es:

static struct Config_t { 
    char protocol[LINE_SIZE]; 
    char mode[LINE_SIZE]; 
} app_cfg; 

Sie noch ein create und destroy zur Verfügung stellen können, die die Struktur zu Nullen memset aber selbst das ist möglicherweise nicht erforderlich:

void create_object (void) { 
    memset(&app_cfg, 0, sizeof(app_cfg)); 
} 

void destroy_config (void) { 
    memset(&app_cfg, 0, sizeof(app_cfg)); 
} 
+0

'memset' wird definitiv nicht benötigt.Es ist garantiert 0-gefüllt, da es statisch ist. Und Destroy scheint auch keinen Sinn zu ergeben. –

+0

@Matthew, ich dachte mehr von dem Fall, wo Sie es vor _reuse_ gelöscht haben wollten, anstatt zunächst zu verwenden. Aber, selbst wenn es bei create/destroy _not_ nicht gelöscht wird, sollten vernünftige Programmierer keinen Code schreiben, der von Werten beeinflusst wird, die herumliegen, daher mein Kommentar "vielleicht nicht erforderlich". – paxdiablo

+0

Ich habe meinen Quellcode geändert und getan, wie Sie es vorgeschlagen haben. Nur eine Frage. In meinem Quellcode benötige ich nur eine Kopie der Strukturvariablen (Stapelebene, statisch global). Ich schätze, wenn ich viele Objekte dieser Struktur erstellen würde und sie für die Lebensdauer der Anwendung verfügbar sein wollte. Ich denke, das ist ein guter Grund, malloc zu benutzen? – ant2009

2

mit diesem Code mit gcc 3.3.3 unter Cygwin funktioniert richtig für mich, wenn ich es zweimal aufrufen. Sie haben uns nicht gesagt, was Sie außerhalb dieser Funktionen tun, also schauen Sie zuerst dort nach, z. Vielleicht weisen Sie versehentlich app_cfg zwischen den Aufrufen einen Wert ungleich Null zu. Wenn Sie keinen "big-name" -Compiler verwenden, besteht die Möglichkeit, dass es sich um einen Compiler-Fehler handelt (z. B. kann er zur Kompilierungszeit zu optimistisch sein und davon ausgehen, dass Sie nie eine NULL an destroy_config übergeben). Versuchen Sie, in etwas setzen wie:

void destroy_config() 
{ 

    /* Check to see if the memory is ok to free */ 
    if(app_cfg != NULL) { 
     printf("not null\n"); 
     free(app_cfg); 
     app_cfg = NULL; 
    }else{ 
     printf("null\n"); 
     } 
} 

, um zu sehen, ob es wirklich „weiß“, wenn es null ist.

+0

Es ist nichts falsch, 'NULL' zu löschen, also ist das nicht die Ursache des Fehlers. Außerdem ist es mit ziemlicher Sicherheit kein Compilerfehler. –