Christoph: (C) seltsamer calloc-Fehler + Pointerfragen

Beitrag lesen

Moin.

Sehr schön: das Speicherleck bei Zuweisung neuer Werte von bezeichnung und zusatzinfo war mir entgangen, was du dank realloc() vermeidest:

  
 void set_str(char **c, const char *s) {  
   int len = strlen(s);  
   if (len>MAX) len=MAX;  
   *c = realloc(*c, (len+1)*sizeof(char));  
   if(!*c) { puts("Kein Speicher mehr(?!)\n"); exit(1); }  
   strncpy(*c, s, len);  
 }  

Trotzdem steckt hier ein Bug: falls strlen(s) == MAX, wird das Null-Endzeichen von s nicht mitkopiert und *c ist nur dann korrekt terminiert, falls zufälligerweise (*c)[len] == 0.

Statt strncpy(*c, s, len) sollte besser

  
    memcpy(*c, s, len);  
    (*c)[len] = 0;  

verwendet werden.

Außerdem ist es in Objekt-orientiertem C üblich, wie in Markus' ursprünglichem Code mit Zeigern auf die Strukturen zu arbeiten. Dabei wird der Code zur Speicherallokation und Initialisierung ausgelagert, was robuster ist: vergisst der Programmierer bei deiner Variante die Initialisierung mit Null-Zeigern, schlägt set_bez() und set_zus() fehl, da realloc() dann ungültige Zeiger übergeben werden.

Ich würde daher folgendes Vorschlagen:

  
void kill_metadata(struct metadata *m)  
{  
    free(m->bezeichnung);  
    free(m->zusatzinfo);  
    free(m);  
}  
  
struct metadata *create_metadata(void)  
{  
    struct metadata *m = malloc(sizeof(*m));  
    if(!m) return NULL;  
  
    m->bezeichnung = NULL;  
    m->zusatzinfo = NULL;  
    return m;  
}  
  
int main(void)  
{  
    struct metadata *m = create_metadata();  
    assert(m);  
  
    set_bez(m, "Erste Zeile");  
    set_zus(m, "Die zweite Zeile ist viel zu lang");  
  
    printf("m->bezeichnung = %s\n"  
           "m->zusatzinfo  = %s\n", m->bezeichnung, m->zusatzinfo);  
  
    kill_metadata(m);  
}  

Christoph