2016-07-11 19 views
0

Derzeit versuche ich den asn1c Compiler zu verstehen. Ich lese gerade durch das PDF https://lionet.info/asn1c/asn1c-usage.pdf. In Abschnitt 2.1.7 die Zielstruktur Freeing ist ein Beispiel wie folgt aus:asn1c: Warum muss ich dieses Mitglied dieser Struktur befreien?

/* 
1. Rectangle_t is defined within my_figure 
*/ 
struct my_figure { 
    Rectangle_t rect; 
} *mf = ...; 

/* 
* Freeing the Rectangle_t* without freeing the mf->rect area. 
*/ 
asn_DEF_Rectangle.free_struct(&asn_DEF_Rectangle, &mf->rect, 1 /* !free */); 

I rect als Teil struct my_figure sehen würde, die in dem gleichen Speicherblock eingebettet ist. Also, warum muss ich diese Struktur mit dieser Funktion befreien? Wenn es den Speicher der Erinnerung nicht freigibt, welcher Zweck dient dieser Funktion?

Die Definition von Rectangle_t wie folgt aussieht:

RectangleTest DEFINITIONS ::= BEGIN 

Rectangle ::= SEQUENCE { 
    height INTEGER, 
    width INTEGER 
} 

END 

Der erzeugte Header

/* 
* Generated by asn1c-0.9.24 (http://lionet.info/asn1c) 
* From ASN.1 module "RectangleTest" 
* found in "../Rectangle.asn1" 
*/ 

#ifndef _Rectangle_H_ 
#define _Rectangle_H_ 


#include <asn_application.h> 

/* Including external dependencies */ 
#include <INTEGER.h> 
#include <constr_SEQUENCE.h> 

#ifdef __cplusplus 
extern "C" { 
#endif 

/* Rectangle */ 
typedef struct Rectangle { 
    INTEGER_t height; 
    INTEGER_t width; 

    /* Context for parsing across buffer boundaries */ 
    asn_struct_ctx_t _asn_ctx; 
} Rectangle_t; 

/* Implementation */ 
extern asn_TYPE_descriptor_t asn_DEF_Rectangle; 

#ifdef __cplusplus 
} 
#endif 

#endif /* _Rectangle_H_ */ 
#include <asn_internal.h> 

Antwort

4

Ich glaube, Sie nicht richtig verstanden, wie die freie Funktion funktioniert. free Ruft einen Zeiger auf die Region, die Sie für Ihre Struktur zugewiesen haben, und dann informiert das Betriebssystem, dass es kein zugewiesener Abschnitt des Speichers mehr ist. Wenn Sie zum Beispiel ein Vektor-Struktur erstellen:

typedef struct Vector2 { 
    float x,y; 
} Vector2; 

// Somewhere in an executing section of code for example you do this 
Vector2 *vec; 
vec = (Vector2*) malloc(sizeof(Vector2)); 

Inzwischen, wie Sie sagten, ist die Vector2 nur sequentielle Daten irgendwo im Speicher (wenn Sie präziser in einer Region sein wollen genannt Haufen). Wenn Sie es sehen könnten, würde es aussehen:

HEAP-MEMORY: ... | float x | float y | ...

, wenn Sie einen zugewiesenen Vector2 befreien wollen, müssen Sie einfach die kostenlose Funktion übergeben seinen Zeiger aufzurufen:

free(vec); 

Dies ist das einfachste Beispiel, weil es nicht mehr Behandlung notwendig ist, anstatt Aufruf der freie Funktion. Das liegt daran, dass die Struktur Vector2 keine Zeiger hat! Wenn die Struktur ist komplexer und hat einige Zeiger, vor der Freigabe der Loch-Sache, müssen Sie müssen befreien alle ihre Zeiger. Das nächste Beispiel ist eine Listenimplementierung, bei der jeder Knoten auf den nächsten Knoten zeigt, bis der letzte Knoten auf NULL zeigt.

typedef struct Node { 
    int data; 
    struct Node* next; 
} Node; 

//Returns a new node 
Node* newNode(){ 
    Node* node = (Node*) malloc(sizeof(Node)); 
    node->next = NULL; 
    return node; 
} 

//Adds new element at tail 
Node* addAtTail(Node* list){ 
    if(list->next != NULL) 
      return addAtTail(list->next); 

    list->next = newNode(); 
    return list->next; 
} 

Wie die nächste Liste in Ihrem Heap-Speicher sein wird?

Node* example_list = newNode(); 
addAtTail(example_list); 
addAtTail(example_list); 
addAtTail(example_list); 

Diese Liste ist die folgende Liste: A -> B -> C -> D -> NULL

Dies ist Ihr heap-SPEICHER:

... {int Daten | Knoten * next} ... {int Daten | Knoten * next} ... {int Daten | Knoten * next} ... {int Daten | Knoten * weiter} ...

Okay. Wie wird Ihr Heap-Speicher, wenn Sie nur die folgende Codezeile aufrufen: free(example_list);? example_list ist der "A" Knoten (der erste Knoten) daher werden Sie nur freien Knoten "A"! So lautet Ihr Heapspeicher jetzt:

... {--------- freigegeben --------} ... {int data | Knoten * next} ... {int Daten | Knoten * weiter} ...{int Daten | Knoten * next} ...

Was passiert mit all diesen Knoten, die Sie nicht freigegeben haben? : D

MEMORY LEAK ist der richtige Ausdruck dafür. Diese schlechten Daten in deinem Gedächtnis haben keine Zeiger auf sie, deshalb sind sie für immer in deinem Gedächtnis verloren und besetzen nur den Raum! In den meisten Anwendungen werden Sie keinen Unterschied bemerken, aber bei kritischen und laufenden Anwendungen ist es sehr wichtig, dass keine Anwendung zum Löschen von Speicherlecks vorhanden ist. Daher ist es sehr empfehlenswert, den Code nicht zu verlecken.

Vielleicht Rectangle_t hat einige Hinweise, die in einer besonderen und einzigartigen Art und Weise :) Die spezielle kostenlose Funktion für unser Beispiel Liste befreit werden müssen, würde so sein:

void freeList(Node* node){ 
    if(node == NULL) 
      return; 
    free_list(node->next); 
    free(node); 
} 

Wenn Sie nicht die Sonderfunktion rufen Sie Um den struct Node zu befreien, wird es einen Speicherverlust geben, deshalb ist es notwendig. Ich nehme an, das ist der gleiche Grund für Rectangle_t

+0

Ja, ich verstehe 'free()' und 'malloc()'. Aber die Frage ist, in diesem Beispiel, sein * not * mf vom Typ 'struct my_figure', der freigegeben wird, * es ist * mf-> rect vom Typ Rectangle_t, der freigegeben wird. –

+0

2.17 "In diesem Beispiel hat der Anwendungsprogrammierer eine benutzerdefinierte Struktur mit einem ASN.1- abgeleiteten Element (rect) definiert. Dieses Element ist keine Referenz auf das Rectangle_t, sondern eine In-Place Aufnahme der Rectangle_t-Struktur .Wenn das Freimachen notwendig ist, darf das übliche Vorgehen von , das alles freigibt, nicht auf den eigentlichen Zeiger selbst angewendet werden, da es nicht auf den von der Speicherzuweisungsroutine direkt zugewiesenen Speicherblock zeigt, sondern innerhalb eines zugewiesenen Blocks liegt die my_figure Struktur. " Ich denke, es ist das, was ich gesagt habe, diese Struktur braucht eine besondere Art der Befreiung –

2

Ich bin kein Experte für ASN.1 oder auf diesem Compiler, aber nach dem Lesen der Dokumentation, ich denke, ich verstehe, was vor sich geht. Ja, in diesem Fall müssen Sie nicht "free_struct" aufrufen, da "rect" nicht von einem Decoder zugewiesen wurde und keine Mitglieder enthält. In gewisser Weise ist dies ein schlechtes Beispiel, sie haben es zu einfach gemacht. Die Dokumentation ist nicht großartig, aber was das Beispiel tut ist, die Verwendung für das letzte Argument zu "free_struct" zu erklären. Nachdem Sie die dekodierte Struktur beendet haben (oder wenn ein Fehler vorliegt), geben Sie sie frei. "free_struct" wird immer den vom Dekoder innerhalb der dekodierten Struktur zugewiesenen Speicher freigeben, aber der Wert des letzten Arguments für "free_struct" sagt ihm, ob er die decodierte Struktur selbst freigeben sollte.

Blick auf das folgende Beispiel:

Rectangle_t * 
simple_deserializer(const void *buffer, size_t buf_size) { 
    asn_dec_rval_t rval; 
    Rectangle_t *rect = 0; /* Note this 01! */ 
    rval = asn_DEF_Rectangle.ber_decoder(0, 
     &asn_DEF_Rectangle, 
     (void **)&rect, /* Decoder moves the pointer */ 
     buffer, buf_size, 0); 
    if (rval.code == RC_OK) { 
     return rect; /* Decoding succeeded */ 
    } 
    else { 
     /* Free partially decoded rect */ 
     asn_DEF_Rectangle.free_struct(&asn_DEF_Rectangle, rect, 
      0); 
     return 0; 
    } 
} 

Wie Sie sehen können, wenn Sie den Decoder rufen Sie einen Zeiger auf einen Zeiger auf die entschlüsselten Struktur übergeben. Beachten Sie auch, dass der Zeiger auf die decodierte Struktur auf 0 initialisiert wird. Ich glaube, dass dies dem Decoder mitteilt, dass es keine decodierte Struktur gibt und dass er Speicher für einen zuweisen muss.

Sie könnten auch den Speicher selbst zugewiesen haben, so.

Rectangle_t * 
simple_deserializer(const void *buffer, size_t buf_size) { 
    asn_dec_rval_t rval; 
    Rectangle_t *rect; 
    if ((rect = malloc(sizeof(Rectangle_t)) == 0) 
     return 0; 
    rval = asn_DEF_Rectangle.ber_decoder(0, 
     &asn_DEF_Rectangle, 
     (void **)&rect, //the decoder realizes that rect is not 0 and does not allocated memory for it. 
     buffer, buf_size, 0); 
    if (rval.code == RC_OK) { 
     return rect; /* Decoding succeeded */ 
    } 
    else { 
     /* Free partially decoded rect */ 
     asn_DEF_Rectangle.free_struct(&asn_DEF_Rectangle, rect, 
      1); 
     free(rect); 
     return 0; 
    } 
} 

In diesem Fall erkennt der Decoder den Zeiger auf die decodierte Struktur nicht 0, so nimmt es eine decodierte Struktur ist und einen Speicher für nicht zugeordnet.

Jetzt für ein Beispiel, wie die, die Sie gab (wo man ein „Rectangle_t“ anstelle eines Zeigers auf einen „Rectangle_t“ haben):

struct my_figure { /* The custom structure */ 
    int flags; /* <some custom member> */ 
    /* The type is generated by the ASN.1 compiler */ 
    Rectangle_t rect; 
    /* other members of the structure */ 
}; 

int 
process_data(const void *buffer, size_t buf_size) { 
    asn_dec_rval_t rval; 
    my_figure mf; 
    Rectangle_t prect; 
    prect = &mf.rect; 
    rval = asn_DEF_Rectangle.ber_decoder(0, 
     &asn_DEF_Rectangle, 
     (void **)&prect, //the decoder realizes that prect is not 0 and assumes it is pointing to a Rectangle_t and does not allocated memory for it. 
     buffer, buf_size, 0); 
    if (rval.code == RC_OK) { 
     //Add code here to process the decoded data. 
     return 0; //return 0 to indicate data processed successfully. 
    } 
    else { 
     /* Free partially decoded rect */ 
     asn_DEF_Rectangle.free_struct(&asn_DEF_Rectangle, prect, 
      1); 
     return 1; //return a non-zero value to indicate data was not processed successfully. 
    } 
} 

In diesem Fall müssen Sie 1 passieren (oder vielleicht irgendeinen Wert ungleich Null, ich weiß es nicht), "free_struct" zu sagen, den Speicher nicht freizugeben, auf den prect zeigt.