N. Charron
N. Charron

Reputation: 11

Strange behavior with dynamic char ** in C

I used to code in C a long time ago and I seem to have lost my chops.

I am experiencing some odd behavior with a dynamic char * array. I have a curses window (implemented in another file) that is to display a list of strings of active CU and TTY devices on my local machine. I attempt to zero-initialize a char ** array with calloc, and then grow it by one appropriate size each time (dir->d_name) matches my string comparisons.

The problem is that these strings display half the time upon running the program, and the other half of the time they are garbled or blank.

I suspect this is a memory/pointer issue related to either malloc() or calloc(), but I have been unable to pinpoint my misunderstanding for several days. Here is the code:

#include <stdio.h>
#include "funcs.h"
#include <ncurses.h>
#include <dirent.h>
#include <string.h>
#include <stdlib.h>

#define arraysize(ar) sizeof(ar)/sizeof(ar[0])

int main(void) 
{
    char ch;
    const char tty[4] = "tty.";
    const char cu[3] = "cu.";
    const char *directory = "/dev/";
    const char **devices = calloc(0,sizeof(const char *));

    // Initial device list gen //

    DIR *d;
    struct dirent *dir; 
    int count=0;
    d = opendir(directory); 
    if (d != NULL)
    {
        while((dir = readdir(d)))
        {
            if(strncmp(dir->d_name,tty,4)==0 || strncmp(dir->d_name,cu,3)==0)
            {
                count++;
                devices = realloc(devices,(count+1)*sizeof(const char *));
                devices[count-1] = (dir->d_name);
            }   
        }
        closedir(d);    
    }
printf("\n%d\n",count);

struct display MAIN = screen_init();

// Display List //

list_devices(devices,count,MAIN.devpad);
while(ch != 'q')
{
    ch = getch();
}
endwin();
}

Thank you for your time/attention.

Upvotes: 1

Views: 46

Answers (1)

tadman
tadman

Reputation: 211710

The biggest problem here is that you're not copying the dir d_name buffer. As the manual says:

The data returned by readdir() may be overwritten by subsequent calls to readdir() for the same directory stream.

This means you need to explicitly copy it:

devices[count-1] = strdup(dir->d_name);

That should eliminate a lot of the garbling.

Upvotes: 2

Related Questions