-2

So i get an segmentation error in C, while runtime (no compiling Error or Warnings with -Wall). I found a solution but do not understand why the error occurred in first place. If someone could explain this to me it would be nice. I'm learning C right now and want to understand it not just have a solution.

void read_dir (const char *path){ 
  DIR *dir;
  struct dirent *object;

  dir = opendir(path);
  if (dir == NULL) return;

  object = readdir(dir);

  while (object != NULL) {
    char *name = object->d_name;
    char fullPath[300];
    sprintf(fullPath, "%s/%s", path, name); 
    object = readdir(dir);  //put it here **error** placement 1

    if (object->d_type == DT_DIR && strcmp(name,".") && strcmp(name,"..")) 
      read_dir (fullPath); 

    object = readdir(dir);// put it here **no error** placement 2
}   
    closedir(dir);
  }

code is running in main like this

int main (){
  read_dir("..");
  return 0;
}

from what i understand seg err/core dump is when reading trying to read memory that does not belong to the program.

And from what i understand about recusion it creates and let my var alive as long as the function does not return so why does that simple change of order changes so much.

Output for placement 1:

../.
../a.out
../scripts
../b.class
../b.java
../..
Segmentation fault (core dumped)

Output for placement 2:

../.
../a.out
../scripts
../scripts/a.c
../scripts/b.c
../scripts/a.txt
../scripts/dir.c
../scripts/.
../scripts/a.out
../scripts/makefile
../scripts/c.c
../scripts/a.class
../scripts/char.c
../scripts/conf.h
../scripts/a.java
../scripts/..
../scripts/dir.backup
../b.class
../b.java
../..```
  • Please shopw the code that calls `read_dir`. Believe it or not, the problem might be there. – Jabberwocky Nov 26 '19 at 16:22
  • Add `printf("%s\n", fullPath);` after the line with `sprintf` and look at the output. That should give you a hint. Also learn how to use your debugger. – Jabberwocky Nov 26 '19 at 16:25
  • 1
    `object->d_type == 4`? Don't use magic numbers like that, use the proper constant supplied by the header. Also, note [the Linux man page entry](http://man7.org/linux/man-pages/man3/readdir.3.html): "Currently, only some filesystems (among them: Btrfs, ext2, ext3, and ext4) have full support for returning the file type in d_type. All applications must properly handle a return of DT_UNKNOWN." – Andrew Henle Nov 26 '19 at 16:30
  • 2
    ... and indent your code correctly. And are you sure the condition `(object->d_type == 4 && strcmp(name,".") & strcmp(name,".."))` is correct? It looks pretty fishy to me. – Jabberwocky Nov 26 '19 at 16:31
  • Where did you put the line `object = readdir(dir);` in the program which segfaults? If you put it after the `if` line, then you changed the meaning of the program. It's better to always write the code targetted by the `if` inside braces `{...}` to avoid errors like that. – rici Nov 26 '19 at 16:45
  • @Jabberwocky i call `read_dir` in main just the function with `(".")` after that `return 0`. The compiler does not output anything even with -Wall. i did the print thing the path is correct. The problem just ocures due runtime. and yes the logic ist right but that is pretty easy logic. Im sorry for the indent i have a small laptop and it is easyer like that. I forgot that –  Nov 26 '19 at 17:11
  • @rici i hightlight it in the good. It should be clearer now –  Nov 26 '19 at 17:16
  • @AlexanderFrey did you do what I suggested in my second comment? What output did you get? – Jabberwocky Nov 26 '19 at 17:27
  • @Jabberwocky yes, i did if the order is write i get something like thie `../scripts/dir.c` started it with (".."). The program is fine it is just the core dump if i change the order. And i do not understand why –  Nov 26 '19 at 17:32
  • @AndrewHenle yes thats right i change it to the const. I read about this too but for my setup it is right. Maybe later i will trie another soulution. Do you hav one i could not find another goodway of reading the file type beside stat. Maybe i should use that –  Nov 26 '19 at 17:35
  • @AlexanderFrey please [edit] your question and put a few lines of real output _there_ – Jabberwocky Nov 26 '19 at 17:35
  • @Jabberwocky just now understood what you mean. editet the question again –  Nov 26 '19 at 18:12

1 Answers1

1
object = readdir(dir);  //put it here **error**

if (object->d_type == DT_DIR && strcmp(name,".") && strcmp(name,"..")) 
  read_dir (fullPath); 

If this call to readdir returns NULL, you still dereference the NULL by trying to test object->d_type which will segfault. You can't change object while you still need to access what it points to.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
  • oh something went wrong with copiny in the original version there is on bracket behind '`object = readdir(dir);` –  Nov 26 '19 at 17:42
  • Can you give us complete code that we can compile and that you have 100% confirmed can reproduce the problem? – David Schwartz Nov 26 '19 at 17:45