0

So I have two simple programs. They are very similar, but one code works just fine and other one doesn't work at all. Does anyone here idea why?

This code works without problems, despite char* name not being initialized.

#include <dirent.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char* argv[]){

   DIR* d;
   struct dirent* dir;
   char* name;
   d=opendir(".");
   if(d){
        while((dir=readdir(d))!=NULL){
             strcpy(name,dir->d_name);
             printf("%s\n",name);
        }
        clode(dir);
   }
  return 0;
}

The second code has minor difference in the declaration section and this results in the variable 'name' being unreachable.

int main(int argc, char* argv[]){

   DIR* d;
   struct dirent* dir;
   char* surname = "Surname";
   char* name;
   d=opendir(".");
   if(d){
        while((dir=readdir(d))!=NULL){
             strcpy(name,dir->d_name);
             printf("%s\n",name);
        }
        clode(dir);
   }
  return 0;
}

When running the second code, I get a "Segmentation fault" immediately after strcpy(name,dir->d_name) and when I try to print variable 'name' under the GDB debugger I get the message $1 = 0x1 <error: Cannot access memory under address 0x1>. Why didn't this error message appear in first program? And what is big deal with declaring char* surname = "Surname"; that makes this kind of runtime error?

P.S. I know that in this example I never use variable 'surname' and I am aware that strcpy(name,dir->d_name) isn't needed in this code. This code is part of much bigger code and this is result of extracting important parts which cause the error (in an attempt to produce a more minimal set of code).

Thank you. Regards

Daniel
  • 854
  • 7
  • 18
Zeljko M
  • 1
  • 2
  • 2
    No memory is allocated for `char* name;` so `strcpy(name,dir->d_name)` will fail. "First code work without problem, despite `char* name` didn't initialized." That was an unlucky break, one outcome of undefined behaviour is code apparently working. – Weather Vane Jan 25 '19 at 01:10
  • Useful to ask, "What value does `name` have with `char* name; ....strcpy(name,dir->d_name);`. As the pointer `name` was never assigned anything, `strcpy(name,...` is receiving garbage. – chux - Reinstate Monica Jan 25 '19 at 01:14

2 Answers2

1

Since name is uninitialized, trying to use strcopy with it is undefined behavior. This means whatever happens is unpredictable and bad code (this doesn't mean it will fail, just that bad things can happen and it should fail. In general, UB may still end up working out, which could be what happened.)

One way you could fix this error is something like:

int main(int argc, char* argv[]){

   DIR* d;
   struct dirent* dir;
   char* surname = "Surname";
   char* name = NULL;

   d=opendir(".");
   if(d){
        while((dir=readdir(d))!=NULL){
             name = realloc(name, strlen(d->name)+1); // Needs to be one char longer 
                                                      // to account for the null terminator.
             strcpy(name,dir->d_name);
             printf("%s\n",name);
        }
        free(name);
        clode(dir);
   }
  return 0;
}
Daniel
  • 854
  • 7
  • 18
  • 1
    malloc(NAME_MAX), not sizeof(char *), which has a value of 1. – Gilbert Jan 25 '19 at 01:21
  • @Gilbert That's assuming there's some maximum size defined (unless you want it to be the absolute largest size possible, but I'm sure you would've said SIZE_MAX ) - that isn't necessary in this case since name is reallocated to fit the size of this string. – Daniel Jan 25 '19 at 01:24
  • Sorry... my bad... I've had too many stupid programming errors of late. – Gilbert Jan 25 '19 at 01:26
  • It's alright, your solution is a good idea since reallocating memory isn't cheap - it's sort of an odd idea to use realloc in this fashion, but afaik it should be well-defined. – Daniel Jan 25 '19 at 01:36
1

char* name; is uninitialized... where it points is undefined. It may work. In may not.

Adding char* surname = "Surname" shifts your variables a bit, allowing name point somewhere else.

What you really need is something like char name[NAME_MAX] to allocate predictable storage.

Gilbert
  • 3,740
  • 17
  • 19
  • Also see https://stackoverflow.com/questions/14115578/why-do-i-have-values-in-my-array-that-i-didnt-assign/14115969#14115969 – Gilbert Jan 25 '19 at 02:09