Ich lese die Namen der momentan bekannten Netzwerkschnittstellen aus /proc/net/dev mit einem kleinen C-Programm aus. Das Programm holt sich eine Zeile mittels readline(), dann untersuche ich, wo der Name der Schnittstelle anfängt (ifname_start) und wo er endet (ifname_end).

Die Namen sollen am Ende in einer char**-Struktur (char **ifnames) sein, die ich der Funktion übergebe. Weil ich natürlich nicht weiß, wie viele Namen im System bekannt sind und wie lang die sind, muß die Struktur dynamisch bei jedem Zeilendurchgang wachsen, was ich mittels realloc() implementiere.

Der relevante Codeabschnitt sieht dann so aus:

Code:
void get_ifnames (char *proc_net_dev_path, struct interfaces *ifs){
    /* Prepare return array. */
    char **ifnames = 0;

    /* Try to open file. */
    
    FILE *fp = fopen (proc_net_dev_path, "r");
    if (fp == NULL) {
        /* Something went wrong. Print an error to stderr and return null. */
        fprintf (stderr, "ERROR: Could not open %s to read interfaces names.\n",
            proc_net_dev_path);
        return;
    }

    /*
        Read line by line from the file. We can throw away the first two lines
        as these are table headers. After that, we read what we get until the
        first double colon ":", because this is the interface name, and throw
        away the spaces.
    */

    /* Count how many interfaces we've got. */
    int iface_count = 0;

    /* Line to read into. Set to NULL to let getline allocate the memory. */
    char *line = 0;

    /* How many bytes we've read. */
    ssize_t read;

    /* The size of the line. */
    size_t len = 0;

    /* Throw away the first two lines, these are only headers. */
    read = getline (&line, &len, fp); free (line); line = 0;
    read = getline (&line, &len, fp); free (line); line = 0;

    /* Now we read what's left over. */
    while ((read = getline (&line, &len, fp)) != -1) {
        /*
            First thing to do: Read until the first double colon, throw away
            spaces, and remeber start and end positions.
        */
        int ifname_start = 0;
        int ifname_end = 0;
        for (size_t i = 0; i != strlen (line); ++i) {
            if (line[i] == '\0' || line[i] == ':') break;
            if (line[i] == ' ') ++ifname_start;
            ++ifname_end;
        }

        /* Resize array, add new interface name. */
        
        ++iface_count;
        char **temp =
		realloc (ifnames, iface_count * sizeof (char*));
        if (!temp) break;
	else ifnames = temp;

        /* Add new interface name */

        char **p = ifnames + iface_count - 1;
        *p = malloc (sizeof (char) * (ifname_end-ifname_start));
        strncpy (*p, (line+ifname_start), ifname_end-ifname_start);

        free (line); line = 0;
    }

    ifs->names = ifnames;
    ifs->num = iface_count;
}
Das funktioniert auch prima. Aber wenn ich Valgrind auf mein Programm ansetze, meldet es ein Speicherleck an der Stelle, an der ich "realloc()" ausführe (Im Quelltext fett markiert). Warum? realloc() vergrößert doch den Speicherbereich, ohne etwas wegzuwerfen? Wenn ich den Zeiger auf den alten Speicherbereich behalte und mit free() versuche, was zu löschen, dann sind meine Daten - logischerweise - immer weg. Ich stehe richtig auf dem Schlauch und habe keinerlei Ahnung, wie ich das Speicherleck beseitigen könnte.

Valgrind meldet auf jeden Fall folgendes:

Code:
==1934== 24 (20 direct, 4 indirect) bytes in 1 blocks are definitely lost in loss record 2 of 4
==1934==    at 0x40204FB: realloc (vg_replace_malloc.c:306)
==1934==    by 0x8048633: get_ifnames (broadcastexample.c:83)
==1934==    by 0x804870D: main (broadcastexample.c:104)
"broadcastexample.c:83" ist genau der realloc()-Aufruf. *grummel*

Hat jemand eine Idee?