Hallo,
ich habe hier ein seltsames Verhalten und hoffe, dass es jemand erklären kann. Ich habe zwei Funktionen, setMetaDataBezeichnung(struct metadata **m, const char *s) und setMetaDataZusatzInfo(struct metadata **m, const char *s):
=== Main.c ===
#include <stdio.h>
#include <stdlib.h> //malloc
#include "metadata.h"
int main(void) {
MetaData m1 = (MetaData)malloc(sizeof(MetaData));
setMetaDataBezeichnung(&m1, "Das ist die erste Bezeichnung");
setMetaDataZusatzInfo(&m1, "Das ist eine zusätzliche Information");
printf("%s\n", getMetaDataBezeichnung(m1));
printf("%s\n", getMetaDataZusatzInfo(m1));
free(m1);
return 0;
}
=== metadata.h ====
#ifndef METADATA_H
#define METADATA_H
#define MAX_INFO 100
#define MAX_BEZ 50
typedef struct metadata *MetaData;
void setMetaDataBezeichnung(struct metadata **m, const char *s);
void setMetaDataZusatzInfo(struct metadata **m, const char *s);
char* getMetaDataBezeichnung();
char* getMetaDataZusatzInfo();
#endif
=== Metadata.c ====
#include <stdio.h>
#include <string.h> //strlen, strncpy
#include <stdlib.h> //calloc
#include "metadata.h"
struct metadata {
char *bezeichnung;
char *zusatzinfo;
};
void setMetaDataBezeichnung(struct metadata **m, const char *s) {
//Falls Zeichenkette länger als MAX_BEZ ist, nur MAX_BEZ+1 (+1 wg. \0) allozieren.
if (strlen(s) >= MAX_BEZ)
(*m)->bezeichnung = (char*)calloc(MAX_BEZ+1,sizeof(char));
else
(*m)->bezeichnung = (char*)calloc(strlen(s)+1,sizeof(char));
if ((*m)->bezeichnung == 0) {
printf("Fehler bei der Speicherallozierung");
exit(1);
}
//Maximal MAX_BEZ Zeichen kopieren. \0 wird automatisch angehängt, da +1 noch frei ist.
strncpy((*m)->bezeichnung, s, MAX_BEZ);
}
void setMetaDataZusatzInfo(struct metadata **m, const char *s) {
//Falls Zeichenkette länger als MAX_INFO ist, nur MAX_INFO+1 (+1 wg. \0) allozieren.
if (strlen(s) >= MAX_INFO)
(*m)->zusatzinfo = (char*)calloc(MAX_INFO+1,sizeof(char));
else
(*m)->zusatzinfo = (char*)calloc(strlen(s)+1,sizeof(char));
if ((*m)->zusatzinfo == 0) {
printf("Fehler bei der Speicherallozierung");
exit(1);
}
//Maximal MAX_INFO Zeichen kopieren. \0 wird automatisch angehängt, da +1 noch frei ist.
strncpy((*m)->zusatzinfo, s, MAX_INFO);
}
char* getMetaDataBezeichnung(struct metadata *m) {
return m->bezeichnung;
}
char* getMetaDataZusatzInfo(struct metadata *m) {
return m->zusatzinfo;
}
Diese Funktionen sind praktisch identisch. Ich kompiliere mit ...
$ gcc Metadata.c Main.c -o Main -std=c99
...was auch durchläuft, aber führe ich nun ./Main aus, bekomme ich seltsamerweise folgende Ausgabe:
markus@archy ~/C-Programme/Projekte/Dateibrowser $ ./Main
Main: malloc.c:3074: sYSMALLOc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 * (sizeof(size_t))) - 1)) & ~((2 * (sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long)old_end & pagemask) == 0)' failed.
Abgebrochen
Was hat das zu bedeuten?
Ironischerweise funktioniert das Ganze aber, wenn ich die Funktion setMetaDataZusatzInfo kommentiere und somit nicht benutze. Wird also nur die erste Funktion aufgerufen funktioniert das Programm und ich bekomme die Ausgabe "Das ist die erste Bezeichnung". Kann sich das jemand erklären?
Meine zweite Frage betrifft die Pointerzuweisung. In metadata.h schreibe ich typedef struct metadata *MetaData; Ich kann nicht typedef struct metadata MetaData; schreiben, damit dieses teils objektorientierte Paradigma funktioniert (eigentlich wollte ich versuchen, die Struktur auf dem Stack zu erzeugen, aber das scheint irgendwie nicht zu funktionieren, da ja dann die Größe der Struktur nicht bekannt ist).
In Main.c ist m1 somit ein Pointer auf eine Struktur MetaData. In &m1 übergebe ich somit die Adresse des Pointers. Um zur Struktur zu gelangen, muss ich in setMetaDataBezeichnung **m offensichtlich doppelt dereferenzieren. Liegt offensichtlich daran, dass der Zeiger nicht die Struktur selbst ist, sondern nur auf die Struktur (die irgendwo im Speicher existiert) zeigt. Ist das richtig so? Ich kann die (funktionierende) erste Funktion setMetaDataBezeichnung auch so hinbiegen, dass ich in der Funktion keine doppelten Referenzen benötige, muss dann aber *&m1 übergeben. Ich mache das immer nach Gefühl, und es funktioniert meistens, aber ich habe da irgendwie noch Vorstellungsschwierigkeiten. *&m1 wäre dann praktisch die dereferenzierte Adresse des Pointer, was dann praktisch die Struktur selbst ist. Deswegen funktioniert dies dann (mit der angepassten Funktion) auch. Ist das richtig so?
Eine letzte Frage hätte ich noch zum Freigeben des Speichers. In Main führe ich ein free(m1) aus, was aber nicht ganz sauber wäre. Ich müsste die einzelnen Variablen der Struktur einzeln für sich auch freigeben, da ein killen der Struktur ja nicht heißt, dass auch die Variablen freigegeben wurden (da sie ja wieder nur Zeiger sind, die irgendwo Platz reserviert haben, der aber selbst auch wieder freigegeben werden muss). Ist das richtig so?
Danke,
Markus