Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Valgrind malloc leaks

I'm writing a program to search though directories for a requested file. The output on command line will be the path of the directory to the file, for each file found with the same name. For some reason it is giving memory leaks when I run it with valgrind. I am running on a linux virtual machine on a windows box.

I updated my valgrind output. I have no leaks free leaks but still errors.

Here's my code:

#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/types.h>
#include <string.h>

struct tree_t {

  char *name;
  int  nchildren;
  struct tree_t **children;
};

char *make_path(const char *dirname, const char *filename) {
  char *fullpath = (char *) malloc((strlen(dirname) + strlen(filename) + 1 + 1) * sizeof(char));
  strcat(fullpath, dirname);
  strcat(fullpath, "/");
  strcat(fullpath, filename);
  return fullpath;
}

struct tree_t *get_tree(const char *name) {
  struct tree_t *tree = (struct tree_t *) malloc(sizeof(struct tree_t)); 
  char *namecp = (char *) malloc((strlen(name) + 1) * sizeof(char));
  strcpy(namecp, name);
  tree->name = namecp;

  DIR *dir = opendir(name);
  if (dir == NULL) {
    tree->nchildren = 0;
  } else {
    tree->nchildren = 0;
    int numsubdirs = 0;

    struct dirent *entry;

    while((entry = readdir(dir))) {
      if (strcmp(entry->d_name,".") != 0 && strcmp(entry->d_name,"..") != 0) {
        tree->nchildren++;  
        DIR *subdir = opendir(entry->d_name);
        if (subdir != NULL) {
          numsubdirs++;
        }
        closedir(subdir);
      }
    }

    tree->children = (struct tree_t **) malloc(numsubdirs * sizeof(struct tree_t **));
  }
  closedir(dir);
  return tree;
}

void find_in_tree(const struct tree_t *root, const char *filename) {
  int i = 0;

  DIR *dir = opendir(root->name);

  if (dir != NULL) {

    struct dirent *entry;

    while((entry = readdir(dir))) {
      if (strcmp(entry->d_name,".") != 0 && strcmp(entry->d_name,"..") != 0) {
        char *fullpath = make_path(root->name, entry->d_name);
        DIR *subdir = opendir(fullpath);
        if (subdir != NULL) {
          root->children[i] = get_tree(fullpath);
          find_in_tree(root->children[i], filename);
          free(root->children[i]);
          i++;
        } else if (strcmp(entry->d_name, filename) == 0) {
          printf("%s\n", fullpath);
        } 
        free(fullpath);
      }
    }
  }

  free(root->name);
  free(root->children);

}

int main(int argc, char **args) {
  printf("What root directory do you want to start from?\n");
  char rootdir[256];
  scanf("%s",rootdir);

  char searchfile[256];
  printf("What file do you want to search for?\n");
  int result = scanf("%s",searchfile);

  if (result == EOF) {
    printf("\n");
    exit(1);
  }

  struct tree_t *root = get_tree(rootdir);
  find_in_tree(root, searchfile);
  free(root);

  return 0;
}

This is what my memcheck looks like after being run.

[vosterjl@clark ~]$ valgrind --tool=memcheck --leak-check=yes -v --track-origins=yes ./dirch
==1464== Memcheck, a memory error detector
==1464== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==1464== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
==1464== Command: ./dirch
==1464==
--1464-- Valgrind options:
--1464--    --tool=memcheck
--1464--    --leak-check=yes
--1464--    -v
--1464--    --track-origins=yes
--1464-- Contents of /proc/version:
--1464--   Linux version 2.6.18-274.17.1.el5 ([email protected]) (gcc version 4.1.2 20080704 (Red Hat 4.1.2-51)) #1 SMP Wed Jan 4 22:45:44 EST 2012
--1464-- Arch and hwcaps: AMD64, amd64-sse3-cx16
--1464-- Page sizes: currently 4096, max supported 4096
--1464-- Valgrind library directory: /usr/lib64/valgrind
--1464-- Reading syms from /USERS/STUDENTS/S-Z/V/VOSTERJL/dirch (0x400000)
--1464-- Reading syms from /usr/lib64/valgrind/memcheck-amd64-linux (0x38000000)
--1464--    object doesn't have a dynamic symbol table
--1464-- Reading syms from /lib64/ld-2.5.so (0x3ca2e00000)
--1464-- Reading suppressions file: /usr/lib64/valgrind/default.supp
--1464-- REDIR: 0x3ca2e14730 (strlen) redirected to 0x3803e767 (vgPlain_amd64_linux_REDIR_FOR_strlen)
--1464-- Reading syms from /usr/lib64/valgrind/vgpreload_core-amd64-linux.so (0x4802000)
--1464-- Reading syms from /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so (0x4a03000)
==1464== WARNING: new redirection conflicts with existing -- ignoring it
--1464--     new: 0x3ca2e14730 (strlen              ) R-> 0x04a070b0 strlen
--1464-- REDIR: 0x3ca2e14550 (index) redirected to 0x4a06f20 (index)
--1464-- REDIR: 0x3ca2e14700 (strcmp) redirected to 0x4a07180 (strcmp)
--1464-- Reading syms from /lib64/libc-2.5.so (0x3ca3200000)
--1464-- REDIR: 0x3ca3279f60 (rindex) redirected to 0x4a06dd0 (rindex)
--1464-- REDIR: 0x3ca3279b70 (strlen) redirected to 0x4a07070 (strlen)
Directory?
dir1
Search file?
test.txt
--1464-- REDIR: 0x3ca3274de0 (malloc) redirected to 0x4a0608a (malloc)
--1464-- REDIR: 0x3ca3279630 (strcpy) redirected to 0x4a08a70 (strcpy)
--1464-- REDIR: 0x3ca327ac80 (memmove) redirected to 0x4a07370 (memmove)
--1464-- REDIR: 0x3ca3272890 (free) redirected to 0x4a05c9a (free)
--1464-- REDIR: 0x3ca3279280 (strcat) redirected to 0x4a07d40 (strcat)
==1464== Invalid write of size 8
==1464==    at 0x400AF3: find_in_tree (in /USERS/STUDENTS/S-Z/V/VOSTERJL/dirch)
==1464==    by 0x400C1F: main (in /USERS/STUDENTS/S-Z/V/VOSTERJL/dirch)
==1464==  Address 0x4c2c170 is 0 bytes after a block of size 0 alloc'd
==1464==    at 0x4A0610C: malloc (vg_replace_malloc.c:195)
==1464==    by 0x4009D2: get_tree (in /USERS/STUDENTS/S-Z/V/VOSTERJL/dirch)
==1464==    by 0x400C0B: main (in /USERS/STUDENTS/S-Z/V/VOSTERJL/dirch)
==1464==
==1464== Invalid read of size 8
==1464==    at 0x400B0B: find_in_tree (in /USERS/STUDENTS/S-Z/V/VOSTERJL/dirch)
==1464==    by 0x400C1F: main (in /USERS/STUDENTS/S-Z/V/VOSTERJL/dirch)
==1464==  Address 0x4c2c170 is 0 bytes after a block of size 0 alloc'd
==1464==    at 0x4A0610C: malloc (vg_replace_malloc.c:195)
==1464==    by 0x4009D2: get_tree (in /USERS/STUDENTS/S-Z/V/VOSTERJL/dirch)
==1464==    by 0x400C0B: main (in /USERS/STUDENTS/S-Z/V/VOSTERJL/dirch)
==1464==
--1464-- REDIR: 0x3ca32795f0 (strcmp) redirected to 0x4a07140 (strcmp)
dir1/dir2/test.txt
==1464== Invalid read of size 8
==1464==    at 0x400B2C: find_in_tree (in /USERS/STUDENTS/S-Z/V/VOSTERJL/dirch)
==1464==    by 0x400C1F: main (in /USERS/STUDENTS/S-Z/V/VOSTERJL/dirch)
==1464==  Address 0x4c2c170 is 0 bytes after a block of size 0 alloc'd
==1464==    at 0x4A0610C: malloc (vg_replace_malloc.c:195)
==1464==    by 0x4009D2: get_tree (in /USERS/STUDENTS/S-Z/V/VOSTERJL/dirch)
==1464==    by 0x400C0B: main (in /USERS/STUDENTS/S-Z/V/VOSTERJL/dirch)
==1464==
dir1/test.txt
Search file?

--1464-- REDIR: 0x3ca327ae20 (memset) redirected to 0x4a07320 (memset)
==1464==
==1464== HEAP SUMMARY:
==1464==     in use at exit: 0 bytes in 0 blocks
==1464==   total heap usage: 22 allocs, 22 frees, 262,763 bytes allocated
==1464==
==1464== All heap blocks were freed -- no leaks are possible
==1464==
==1464== ERROR SUMMARY: 6 errors from 3 contexts (suppressed: 4 from 4)
==1464==
==1464== 2 errors in context 1 of 3:
==1464== Invalid read of size 8
==1464==    at 0x400B2C: find_in_tree (in /USERS/STUDENTS/S-Z/V/VOSTERJL/dirch)
==1464==    by 0x400C1F: main (in /USERS/STUDENTS/S-Z/V/VOSTERJL/dirch)
==1464==  Address 0x4c2c170 is 0 bytes after a block of size 0 alloc'd
==1464==    at 0x4A0610C: malloc (vg_replace_malloc.c:195)
==1464==    by 0x4009D2: get_tree (in /USERS/STUDENTS/S-Z/V/VOSTERJL/dirch)
==1464==    by 0x400C0B: main (in /USERS/STUDENTS/S-Z/V/VOSTERJL/dirch)
==1464==
==1464==
==1464== 2 errors in context 2 of 3:
==1464== Invalid read of size 8
==1464==    at 0x400B0B: find_in_tree (in /USERS/STUDENTS/S-Z/V/VOSTERJL/dirch)
==1464==    by 0x400C1F: main (in /USERS/STUDENTS/S-Z/V/VOSTERJL/dirch)
==1464==  Address 0x4c2c170 is 0 bytes after a block of size 0 alloc'd
==1464==    at 0x4A0610C: malloc (vg_replace_malloc.c:195)
==1464==    by 0x4009D2: get_tree (in /USERS/STUDENTS/S-Z/V/VOSTERJL/dirch)
==1464==    by 0x400C0B: main (in /USERS/STUDENTS/S-Z/V/VOSTERJL/dirch)
==1464==
==1464==
==1464== 2 errors in context 3 of 3:
==1464== Invalid write of size 8
==1464==    at 0x400AF3: find_in_tree (in /USERS/STUDENTS/S-Z/V/VOSTERJL/dirch)
==1464==    by 0x400C1F: main (in /USERS/STUDENTS/S-Z/V/VOSTERJL/dirch)
==1464==  Address 0x4c2c170 is 0 bytes after a block of size 0 alloc'd
==1464==    at 0x4A0610C: malloc (vg_replace_malloc.c:195)
==1464==    by 0x4009D2: get_tree (in /USERS/STUDENTS/S-Z/V/VOSTERJL/dirch)
==1464==    by 0x400C0B: main (in /USERS/STUDENTS/S-Z/V/VOSTERJL/dirch)
==1464==
--1464--
--1464-- used_suppression:      4 dl-hack3
==1464==
==1464== ERROR SUMMARY: 6 errors from 3 contexts (suppressed: 4 from 4)

Anything will help, thanks!

like image 252
Jake Vosters Avatar asked Feb 21 '23 05:02

Jake Vosters


2 Answers

For each opendir you do, you should close with a closedir Please check. This can be source of your leaks.

Valgrind is also pointing this out to you

==468== 65,648 bytes in 2 blocks are definitely lost in loss record 3 of 3 
==468==    at 0x4A0610C: malloc (vg_replace_malloc.c:195) 
==468==    by 0x3CA3296822: __alloc_dir (in /lib64/libc-2.5.so) 
==468==    by 0x400A09: find_in_tree (in /USERS/STUDENTS/S-Z/V/VOSTERJL/dirch) 
==468==    by 0x400B0F: find_in_tree (in /USERS/STUDENTS/S-Z/V/VOSTERJL/dirch) 
==468==    by 0x400C06: main (in /USERS/STUDENTS/S-Z/V/VOSTERJL/dirch) 
like image 182
Jay Avatar answered Feb 28 '23 00:02

Jay


Trust valgrind and not your code.

For instance:

char *make_path(const char *dirname, const char *filename) {
    char *fullpath = (char *) malloc((strlen(dirname) + strlen(filename) + 1 + 1) * sizeof(char));
    strcat(fullpath, dirname);

The memory returned by malloc() is not initialized. You can't use strcat() yet.

There will be other problems of a similar ilk, no doubt.

like image 30
Jonathan Leffler Avatar answered Feb 28 '23 00:02

Jonathan Leffler