2016-08-17 3 views
1

Ich habe eine Funktion, die einen char * Zeiger in C zurückgibt, wie diese, ich zuweisen diese (mit iso_c_binding)Freigeben eines C-Zeigers, der von einer C-Funktion an Fortran zurückgegeben wird?

type (c_ptr) :: C_String_ptr 
... 
C_String_ptr = string_val (ARGS) 

Dieses Teil funktioniert gut mit einem C-Zeiger

char * string_val (ARGS) 
{ 
char * svalue = cJSON_GetObjectItem(nml,var_name)->valuestring; 
return svalue; 
} 

In Fortran sieht . Die Funktion string_val wird sehr oft aufgerufen, und ich denke, es verursacht einen Speicherverlust. Ich versuche, den Speicher des Svalue-Zeigers freizugeben, aber ich habe gerade in seg-Fehler und Speicherauszüge geraten. Im Moment habe ich so etwas wie diese:

 subroutine c_mem_free (cptr) bind(C,name="c_mem_free") 
     use iso_c_binding 
     type (c_ptr) :: cptr !< The C pointer whose memory needs to be freed 
    end subroutine 
... 
call c_mem_free(C_String_ptr) 

wo

void c_mem_free (void** addrOfptr) 
{ 
    free(*addrOfptr); /* free the memory pointed to */ 
    *addrOfptr=NULL;  /* Nullify the pointer ;) */ 
} 

Die Traceback-Punkte für ein Problem auf der freien Linie. Ich habe auch versucht, ändern cptr zu Wert so type (c_ptr),VALUE :: cptr und mit void*addrOfptr und free(addrOfptr) auf der C-Seite, aber das schien auch nicht zu arbeiten. Es ist mir auch nicht gelungen, den Speicherort von svalue auf der Fortran-Seite zu finden. Wenn ich so etwas wie

write (6,'(z)')loc(C_String_ptr) write (6,'(z)')loc(c_loc(C_String_ptr))

beides nicht verwenden, gibt mir den gleichen Wert wie wenn ich die Stelle des Speichers von sValue printf. Wie kann ich den Speicher des Zeiger svalue freigeben, nachdem es in Fortran zurückgegeben wurde? Wie kann ich den Speicherort des Svalue-Speichers in Fortran erhalten?

+3

Welcher Mechanismus wird von cJSON zur Verfügung gestellt, um den Speicher freizugeben, wenn das Programm vollständig in C geschrieben wurde? Wenn man bedenkt, dass Sie kein explizites malloc haben, denke ich, dass jedes Speicherleck, das Sie haben, aufgrund des von cJSON zugewiesenen Speichers auftritt, nein? Wenn dies der Fall ist, würde ich meinen, dass "c_mem_free" auch den von cJSON bereitgestellten Mechanismus verwenden sollte.Ein Fehlerbehebungsschritt wäre, ein kleines Programm mit einer solchen cJSON-Zuweisung in eine Schleife zu schreiben und zu versuchen, das Speicherleck zuerst mit dem gesamten Programm in C und dann mit C + Fortran zu demonstrieren. –

+0

Ich denke, ein JSON-Tag sollte hinzugefügt werden. Ich weiß nicht welche, also werde ich das nicht machen. –

+0

@ DouglasB.Staple 'für (a = 1; a <1000000; a = a + 1) { cJSON * nml = getnml (mein_json_string, nml_name, var_name); svalue = cJSON_GetObjectItem (nml, var_name) -> Wertstring; // Finde den Zeichenfolgenwert frei (nml); frei (svalue); if (a% 10000 == 0) {printf ("a/n");} ' Das erzeugt kein Leck. Die Erinnerung bleibt ungefähr gleich. Ohne free (svalue) geht der verwendete Speicher weit nach oben. cJSON hat eine cJSON_free, die nur frei verwendet. – byrdman1982

Antwort

1

Als Daumen hoch Regel sollten Sie Speicher nicht außerhalb Ihres Codes "freigeben". Und das gilt auch für cJSON.

Sobald Sie das Objekt analysieren, ist der Baum im Speicher aufzubauen und Sie können die Objekte, ihre Werte zu erreichen, ändern Sie es, usw.

Nachdem Sie die Bearbeitung Ihrer Datei abgeschlossen haben, können Sie den Speicher frei telefonieren cJSON_Delete (Wurzel);

Diese Routine kümmert sich um alles für Sie.

Wenn Sie Objekte/Knoten freigeben möchten, während Sie sie verwenden, können Sie auch verwenden cJSON_Delete (Knoten); Denken Sie daran, dass diese Routine "rekursiv" ist. Also, wenn Sie einen Knoten befreien, wird es alle Kinder frei und auch die Geschwister, wie Sie durch den Code hier sehen können:

/* Delete a cJSON structure. */ 
void cJSON_Delete(cJSON *c) 
{ 
    cJSON *next; 
    while (c) 
    { 
     next=c->next; 
     if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child); 
     if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring); 
     if (!(c->type&cJSON_StringIsConst) && c->string) cJSON_free(c->string); 
     cJSON_free(c); 
     c=next; 
    } 
} 

NICHT verwenden cJSON_Free, als cJSON_Delete Pflege nehmen von allem, während cJSON_free auf die internen Elemente der Struktur angewendet werden muss, bevor die Struktur selbst freigegeben wird, andernfalls haben Sie ein Speicherleck.

+0

mit cJSON_Delete funktioniert in meinen Funktionen für doubles und Integer, aber wenn ich es in meinen String-Funktionen verwende, habe ich am Ende leere Zeichenfolgen, weil die Zeichenfolge als Zeiger übergeben wird. – byrdman1982

+1

@ byrdman1982, dies ist das erwartete Verhalten, da sie Zeiger sind. Wenn Sie die Zeichenfolge nach dem Lesen aus der JSON-Struktur behalten möchten, sollten Sie sie in eine Zeichenfolge kopieren. Die Frage, die ich mir immer wieder stelle ist, warum musst du sofort frei machen? Per Definition ist ein Speicherleck ein Problem im Code, das dazu führt, dass der zugewiesene Speicher nicht mehr zugänglich ist, weil z. B. ein Zeiger den Gültigkeitsbereich verlässt. Sind Sie sicher, dass cJSON das tut? – Jauch

+0

Was genau sehen Sie, dass Sie denken, Sie haben ein Speicherleck? – Jauch

Verwandte Themen