Thread: Seg fault when accessing double pointer

  1. #1
    Registered User
    Join Date
    Dec 2009
    Posts
    42

    Unhappy Seg fault when accessing double pointer

    Hello There,

    I wrote a function that reads out all the files in a certain directory and it's writing them into an array of character arrays that was passed. The function looks like this:
    Code:
    int getdir(char *path, char **filelist)
    {
      int items=0;
      char **temp=NULL;
      char filename[1024]={0};
      struct dirent *dp;
      DIR *dir = opendir(path);
      if (dir==NULL){
        syslog(LOG_ALERT, "Error opening log_record directory %s", path);
        printf("Error opening log_record directory %s", path);
        return -1;
      }
      while((dp=readdir(dir))!=NULL){
        if(strstr(dp->d_name, "log_record")!=NULL){
          sprintf(filename,"%s%s",path,dp->d_name);      
          syslog(LOG_ALERT, "%s\n",filename);
          temp = realloc(filelist, (items+1) * sizeof(*temp));
          if (temp == NULL) {
            while (--items >= 0)
              free (filelist[items]);
            free (filelist);
            syslog(LOG_ALERT, "Error reallocating memory for filelist\n");
    	printf("Error reallocating memory for filelist\n");
            return -1;
          }
          filelist = temp;
          filelist[items] = calloc(strlen(filename)+1,sizeof(char));
          if (filelist[items] == NULL) {
            syslog(LOG_ALERT, "Error reallocating memory for filename\n");
    	printf("Error reallocating memory for filename\n");
            return -1;
          }
          strcpy (filelist[items], filename);
          ++items;
        }    
      }
      printf("filelist[%d]: %s\n",items-1,filelist[items-1]);
      return items;
    }
    now thaty printf on the bottom there works just fine. I do call the function like this:
    Code:
          files=getdir("/usr/share/NovaxTSP/", list);
          printf("files %d\n",files);
          printf("list[0] %s\n ",list[0]);
    where list is of type char**. Now my printf here (to print list[0]) seg faults out, why? I don't understand...
    Any clues?
    elp is appreciated!
    Thank you!
    Ron

  2. #2
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Have you malloc'd storage for filelist before doing so for the array of char pointers it points to?

  3. #3
    Registered User
    Join Date
    Dec 2009
    Posts
    42
    Quote Originally Posted by itCbitC View Post
    Have you malloc'd storage for filelist before doing so for the array of char pointers it points to?
    Well, I have declared char **list=NULL; in my caller function and i do a
    Code:
    temp = realloc(filelist, (items+1) * sizeof(*temp));
          if (temp == NULL) {
            while (--items >= 0)
              free (filelist[items]);
            free (filelist);
            syslog(LOG_ALERT, "Error reallocating memory for filelist\n");
    	printf("Error reallocating memory for filelist\n");
            return -1;
          }
          filelist = temp;
    in my getdir() function which should take care of that, wouldn't it? I'm passing the reference of list to getdir() where it's called filelist... Should work after me, no?

  4. #4
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    Code:
    temp = realloc(filelist, (items+1) * sizeof(*temp));
    How many bytes of memory do you think this is allocating? I bet if you printed out the value of items and sizeof(*temp), you would be surprised.

    Well, I have declared char **list=NULL; in my caller function and i do a ... in my getdir() function which should take care of that, wouldn't it?
    Nope. The memory you allocate in the function is lost since you don't return it to the caller.
    bit∙hub [bit-huhb] n. A source and destination for information.

  5. #5
    Registered User
    Join Date
    Dec 2009
    Posts
    42
    Quote Originally Posted by bithub View Post
    Code:
    temp = realloc(filelist, (items+1) * sizeof(*temp));
    How many bytes of memory do you think this is allocating? I bet if you printed out the value of items and sizeof(*temp), you would be surprised.
    I made a printf("DEBUG: realloc:%dBytes\n",(items+1) * sizeof(*temp)); right after the realloc and it prints: DEBUG: realloc:4Bytes which sounds pretty good to me, no?
    Quote Originally Posted by bithub View Post
    Nope. The memory you allocate in the function is lost since you don't return it to the caller.
    Huh but I pass the function a reference from the caller and then allocate memory at this address - how does this get lost again and also how can i return it to the caller?
    I didn't know of that, doesn't make sense to me....

  6. #6
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    Quote Originally Posted by cerr View Post
    I made a printf("DEBUG: realloc:%dBytes\n",(items+1) * sizeof(*temp)); right after the realloc and it prints: DEBUG: realloc:4Bytes which sounds pretty good to me, no?
    I didn't see the second calloc() down below, I thought that was your only memory allocation.

    Quote Originally Posted by cerr View Post
    Huh but I pass the function a reference from the caller and then allocate memory at this address - how does this get lost again and also how can i return it to the caller?
    I didn't know of that, doesn't make sense to me....
    You're not passing a reference to anything. You are passing a pointer to a pointer, but in the function you ignore what is passed in, and overwrite it after your realloc() call. You need something like this instead:

    Code:
    char **list;
    getdir("path", &list);
    
    int getdir(char *path, char ***filelist)
    {
    ...
    *filelist = temp;
    This way the caller actually has access to the memory you allocate.
    bit∙hub [bit-huhb] n. A source and destination for information.

  7. #7
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Pass the address of list to getdir(), tho' now you have to deal with three levels of indirection.

  8. #8
    Registered User
    Join Date
    Dec 2009
    Posts
    42

    Thumbs up

    Quote Originally Posted by itCbitC View Post
    Pass the address of list to getdir(), tho' now you have to deal with three levels of indirection.
    Yes, this actually worked out nicely, thank you!

  9. #9
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    For what it's worth, calloc() zeros out the memory it allocates, but you go and overwrite the data with a strcpy() immediately afterwards -- so I'd be inclined to use malloc() instead of calloc() to avoid this.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  10. #10
    Registered User
    Join Date
    Dec 2009
    Posts
    42
    Quote Originally Posted by dwks View Post
    For what it's worth, calloc() zeros out the memory it allocates, but you go and overwrite the data with a strcpy() immediately afterwards -- so I'd be inclined to use malloc() instead of calloc() to avoid this.
    What's the advantage of using malloc instead of calloc then?

  11. #11
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    I guess I wasn't clear: if you use calloc(), you zero the memory and then overwrite it. If you use malloc(), you never spend time zeroing memory which is just going to be overwritten anyway.

    Of course it doesn't make much difference at all really.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  12. #12
    Registered User
    Join Date
    Dec 2009
    Posts
    42
    Quote Originally Posted by dwks View Post
    I guess I wasn't clear: if you use calloc(), you zero the memory and then overwrite it. If you use malloc(), you never spend time zeroing memory which is just going to be overwritten anyway.

    Of course it doesn't make much difference at all really.
    Nevertheless I changed it to
    Code:
    (*filelist[items]) = malloc(strlen(filename)+1);

  13. #13
    Registered User
    Join Date
    Dec 2009
    Posts
    42
    Quote Originally Posted by cerr View Post
    Nevertheless I changed it to
    Code:
    (*filelist[items]) = malloc(strlen(filename)+1);
    Actually, I have another problem there, let's say that there's more than 1 file in this directory.
    Code snippet:
    Code:
    (*filelist) = temp;
          printf("DEBUG: filename:%s, items:%d\n",filename,items);
          (*filelist[items]) = malloc(strlen(filename)+1);
          printf("DEBUG: After malloc %p\n",(*filelist[items]));
          if ((*filelist[items]) == NULL) {
            syslog(LOG_NOTICE, "nlog: Error reallocating memory for filename\n");
    	printf("Error reallocating memory for filename\n");
            return -1;
          }
    returns me following:
    DEBUG: filename:/usr/share/NovaxTSP/log_record20091229, items:0
    DEBUG: After malloc 0x8f0b3a0
    DEBUG: filename:/usr/share/NovaxTSP/log_record20091230, items:1
    Segmentation fault


    Why can't i malloc space for the 2nd element in where items = 1. above I did reallocate filellist so that there should be enough room for it:
    Code:
      while((dp=readdir(dir))!=NULL){
        if(strstr(dp->d_name, "log_record")!=NULL){
          sprintf(filename,"%s%s",path,dp->d_name);      
          syslog(LOG_NOTICE, "nlog: %s\n",filename);
          temp = realloc((*filelist), (items+1) * sizeof(*temp));
          if (temp == NULL) {
            while (--items >= 0)
              free ((*filelist[items]));
            free ((*filelist));
            syslog(LOG_NOTICE, "nlog: Error reallocating memory for filelist\n");
    	printf("Error reallocating memory for filelist\n");
            return -1;
          }
          (*filelist) = temp;
          printf("DEBUG: filename:%s, items:%d\n",filename,items);
          (*filelist[items]) = malloc(strlen(filename)+1);
          printf("DEBUG: After malloc %p\n",(*filelist[items]));
          if ((*filelist[items]) == NULL) {
            syslog(LOG_NOTICE, "nlog: Error reallocating memory for filename\n");
    	printf("Error reallocating memory for filename\n");
            return -1;
          }
          strcpy ((*filelist[items]), filename);
          ++items;
        }    
      }

  14. #14
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Code:
    (*filelist[items]) = malloc(strlen(filename)+1);
    Instead of that you probably want
    Code:
    (*filelist)[items] = malloc(strlen(filename)+1);
    assuming that filelist is a char*** as bithub and itCbitC suggested.

    The thing is that (*filelist[items]) says "get index items of filelist, then dereference", whereas you probably want "dereference filelist, then get index items".
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  15. #15
    Registered User
    Join Date
    Dec 2009
    Posts
    42
    Quote Originally Posted by dwks View Post
    Code:
    (*filelist[items]) = malloc(strlen(filename)+1);
    Instead of that you probably want
    Code:
    (*filelist)[items] = malloc(strlen(filename)+1);
    assuming that filelist is a char*** as bithub and itCbitC suggested.

    The thing is that (*filelist[items]) says "get index items of filelist, then dereference", whereas you probably want "dereference filelist, then get index items".
    Exaactly, I didn't take into account that [] is basically already dereferencing the actual value and hence i "only" need to dereference the list. Is that correct...Oh man, that's confusing
    Thanks a lot for everyone's help!!!!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Can someone help with my seg fault?
    By John_L in forum C++ Programming
    Replies: 23
    Last Post: 03-01-2008, 04:04 PM
  2. Replies: 2
    Last Post: 09-09-2007, 12:58 AM
  3. need some help with last part of arrays
    By Lince in forum C Programming
    Replies: 3
    Last Post: 11-18-2006, 09:13 AM
  4. Help with multi function progam
    By WackoWolf in forum C Programming
    Replies: 22
    Last Post: 10-13-2005, 02:56 AM
  5. Seg Fault Problem
    By ChazWest in forum C++ Programming
    Replies: 2
    Last Post: 04-18-2002, 03:24 PM

Tags for this Thread