0

Given this code , which is a part of a bigger code , but it's the blame .

In int main() I do this :

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

// code 

// code 

path2 = (char*)malloc(strlen(currentDir)*sizeof(char));

traverseDirectories(path2 , filename);

free(path2);
}

The error :

a@ubuntu:~/Desktop$ ./exer4 fsdfsdfdafsd/ exer4
Could not open: No such file or directory
*** glibc detected *** ./exer4: free(): invalid next size (normal): 0x08b54038 ***
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(+0x6ebc2)[0x93ebc2]
/lib/i386-linux-gnu/libc.so.6(+0x6f862)[0x93f862]
/lib/i386-linux-gnu/libc.so.6(cfree+0x6d)[0x94294d]
/lib/i386-linux-gnu/libc.so.6(fclose+0x154)[0x92e0b4]
/lib/i386-linux-gnu/libc.so.6(perror+0xc5)[0x920a45]
./exer4[0x8048f52]
./exer4[0x8048b34]
./exer4[0x8048a99]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0x8e9113]
./exer4[0x80487c1]
======= Memory map: ========
00398000-003b4000 r-xp 00000000 08:01 394171     /lib/i386-linux-gnu/libgcc_s.so.1
003b4000-003b5000 r--p 0001b000 08:01 394171     /lib/i386-linux-gnu/libgcc_s.so.1
003b5000-003b6000 rw-p 0001c000 08:01 394171     /lib/i386-linux-gnu/libgcc_s.so.1
008d0000-00a46000 r-xp 00000000 08:01 394150     /lib/i386-linux-gnu/libc-2.13.so
00a46000-00a48000 r--p 00176000 08:01 394150     /lib/i386-linux-gnu/libc-2.13.so
00a48000-00a49000 rw-p 00178000 08:01 394150     /lib/i386-linux-gnu/libc-2.13.so
00a49000-00a4c000 rw-p 00000000 00:00 0 
00b5a000-00b5b000 r-xp 00000000 00:00 0          [vdso]
00c4b000-00c69000 r-xp 00000000 08:01 394137     /lib/i386-linux-gnu/ld-2.13.so
00c69000-00c6a000 r--p 0001d000 08:01 394137     /lib/i386-linux-gnu/ld-2.13.so
00c6a000-00c6b000 rw-p 0001e000 08:01 394137     /lib/i386-linux-gnu/ld-2.13.so
08048000-0804a000 r-xp 00000000 08:01 947365     /home/a/Desktop/exer4
0804a000-0804b000 r--p 00001000 08:01 947365     /home/a/Desktop/exer4
0804b000-0804c000 rw-p 00002000 08:01 947365     /home/a/Desktop/exer4
08b54000-08b75000 rw-p 00000000 00:00 0          [heap]
b7600000-b7621000 rw-p 00000000 00:00 0 
b7621000-b7700000 ---p 00000000 00:00 0 
b775f000-b7760000 rw-p 00000000 00:00 0 
b776f000-b7771000 rw-p 00000000 00:00 0 
bf87d000-bf89e000 rw-p 00000000 00:00 0          [stack]
Aborted

And here are the methods :

int traverseDirectories(char * path , const char * filename)
{

    // printf("\nCurrent path is :%s\n " , path);
    struct dirent *direntp = NULL;
    DIR *dirp = NULL;
    size_t path_len;
    char full_name[BUFFER];
    strcpy(full_name, path);

    displayAllFiles(full_name , filename);  // display the file details to STDOUT

// code 
// code 

}


void displayAllFiles(char * directory , char * filename)
{
    struct stat st;
    DIR *dir;
    struct dirent *ent;

    char fullPathDirectory[BUFFER];
    char fileDetails[BUFFER];

    memset(fullPathDirectory, '\0', BUFFER);   // reset the array of the input
    memset(fileDetails, '\0', BUFFER);   // reset the array of the input

    dir = opendir (directory);

    if (dir != NULL)
    {

         // print all the files and directories within directory
         while ((ent = readdir (dir)) != NULL)
         {
             if (strcmp(ent->d_name , filename) == 0)
             {
                  // printf("\nFile found!\n");

                  strcpy(fullPathDirectory , directory);
                  strcat(fullPathDirectory , "/");
                  strcat(fullPathDirectory , filename);

                  if (lstat(fullPathDirectory, &st) < 0)
                  {
                      perror(ent->d_name);
                      putchar('\n');
                      continue;
                  }

                  displayProperties(&st , fileDetails);

                  printf("\n%s" , fileDetails); // print file details
                  printf("%s\n" , fullPathDirectory); // print file path
             }

         }
         closedir (dir);
    }

    else
    {
     // could not open directory
     perror ("Could not open");
     free(directory);
     exit(EXIT_FAILURE);
    }

}

I free the directory in method displayAllFiles , but even though I get this message when executing :

./exer4 fsdfsdfdafsd/ exer4

The program doesn't find the folder fsdfsdfdafsd , and this is OK , but why does it print all the backtrace ? all I wanted it to do is to print that no such file or directory .

Any ideas ?

Thanks

JAN
  • 21,236
  • 66
  • 181
  • 318
  • By the way, sizeof(char) is redundant, as it's guaranteed to be 1 by the C standards. – yasar Jun 19 '12 at 10:09
  • use valgrind + gdb to understand your fault –  Jun 19 '12 at 10:29
  • @yasar11732 Where? As far as I know, the only thing guaranteed by the C standard is that `char` is at least 8 bits. – Lundin Jun 19 '12 at 11:42
  • @Lundin: read 6.2.5 and 6.2.6 in the n1570.pdf file. – pmg Jun 19 '12 at 11:51
  • @pmg I have no idea what that pdf is. The standard ISO 9899:2011 6.2.5/3 only says: "An object declared as type char is large enough to store any member of the basic execution character set. If a member of the basic execution character set is stored in a char object, its value is guaranteed to be nonnegative. If any other character is stored in a char object, the resulting value is implementation-defined but shall be within the range of values that can be represented in that type." – Lundin Jun 19 '12 at 12:01
  • The [n1570.pdf file is available online](http://www.open-std.org/JTC1/sc22/wg14/www/docs/n869/n869.txt.gz). It is a draft of the most current C Standard. Footnote 49 (in 6.2.6.1/3) says "**A byte contains CHAR_BIT bits**": the same information can be deduced by reading the text. – pmg Jun 19 '12 at 12:05
  • Note also that in C it's redundant (and potentially dangerous) to cast the result of malloc, i.e. it should just be: `path2 = malloc(strlen(currentDir) + 1);` – Paul R Jun 20 '12 at 09:33

5 Answers5

4

A few quick observations:

  1. Don't cast the return of malloc().
  2. sizeof (char) is 1.
  3. Strings need room for the '\0' termination character.
Community
  • 1
  • 1
unwind
  • 391,730
  • 64
  • 469
  • 606
  • Where in the C standard does it state that sizeof(char) is 1? As far as I know, the only thing guaranteed by the C standard is that `char` is at least 8 bits. – Lundin Jun 19 '12 at 11:43
  • @unwind: Can you please explain `(1)Don't cast the return of malloc()` ? Why is it wrong to do so ? – JAN Jun 19 '12 at 13:45
  • 1
    @ron It hides potential problems such as a forgotten `#include`. – glglgl Jun 19 '12 at 14:37
1

You call free(directory) in displayAllFiles() when directory comes from a local variable in traverseDirectories().

Generally, you shouldn't call exit() there, but just return a indicator for an error, which the caller can (and should) handle.

glglgl
  • 89,107
  • 13
  • 149
  • 217
1

This is some piece of your code.

char full_name[BUFFER];    
displayAllFiles(full_name , filename); 
.....
void displayAllFiles(char * directory , char * filename)
....
free(directory);

argument directory is not allocated by malloc, free a address that is not allocated by malloc will cause undefined behavior.

MYMNeo
  • 818
  • 5
  • 9
  • But I use allocation for that in `int main()` , doesn't it matter ? or what you're saying that `int main()` must free the allocated memory , and no other method ? – JAN Jun 19 '12 at 13:23
  • @ron, you have mistaken my opinion, your statement `free(path2)` is valid,but statement `free(directory)` is invalid. – MYMNeo Jun 19 '12 at 13:27
1

I write a test code to simulate your problem.

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 
  4 void problem(char * addr)
  5 {
  6     free(addr);
  7 }
  8 
  9 int func(char * buf)
 10 {
 11     char name[10];
 12 
 13 
 14 
 15     problem(name);
 16 
 17     return 0;
 18 }
 19 
 20 int main(void)
 21 {
 22     char *string;
 23 
 24     string = NULL;
 25     string = malloc(10);
 26     if(string == NULL)
 27         return -1;
 28 
 29     func(string);
 30     free(string);
 31     return 0;
 32 }
 33 

run valgrind give the message.

==17451== Invalid free() / delete / delete[] / realloc()
==17451==    at 0x59CFC: free (in /usr/local/lib/valgrind/vgpreload_memcheck-x86-freebsd.so)
==17451==    by 0x8048490: problem (main.c:6)
==17451==    by 0x80484B0: func (main.c:15)
==17451==    by 0x8048500: main (main.c:29)
==17451==  Address 0xbebfec2e is on thread 1's stack

You can not free a address that is not allocate by malloc, it will cause a problem.

MYMNeo
  • 818
  • 5
  • 9
0

The problem is here :

a@ubuntu:~/Desktop$ ./exer4 fsdfsdfdafsd/ exer4
Could not open: No such file or directory
*** glibc detected *** ./exer4: free(): invalid next size (normal): 0x08b54038 ***

The thing is , when I allocate this :

path2 = (char*)malloc(strlen(currentDir)*sizeof(char));

and later on change the size of the string that path2 points to , and I try to free back in main a string with a length of strlen(currentDir) , then I get this :

 invalid next size (normal): 0x08b54038 ***

This means that I try to free a memory with some other size , and this is incorrect of course . That's why I did this : path2 = malloc(BUFFER*sizeof(char)); , and everything worked out OK .

Thanks everybody !

JAN
  • 21,236
  • 66
  • 181
  • 318
  • @MYMNeo: I have , that's why I did what is written in my answer , based on your answer :) – JAN Jun 19 '12 at 13:41