Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

realloc fails when printf is in code / weird chars

I try to program a simple implementation of ls for school

#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
int normalsort( const void *string1, const void *string2) {
    char *const *char1 = string1;
    char *const *char2 = string2;
    return strcasecmp(*char1, *char2);
}

int listDir (char* path, int listToggeled, int classifyToggeled){
    DIR *dir = opendir(path);
    struct dirent *entry;
    struct stat s;
    char** listofentries;
    char symbol = '-';
    int counter = 0;





    while ((entry = readdir(dir)) != NULL){
        if (entry->d_name[0] != '.'){
            listofentries = realloc(listofentries, (counter + 1) * sizeof(char*));
            listofentries[counter] = entry->d_name;
            counter++;
        }
    }

    qsort(listofentries, counter, sizeof(char*), normalsort);

    for (int i = 0; i < counter; i++){
        char* entryname = listofentries[i];
        if (entryname[0] != '.'){
            printf("%s", entryname);

            if (classifyToggeled == 1){
                lstat(entryname, &s);

                if (S_ISDIR(s.st_mode)) {
                    symbol = '/';
                } else if (S_ISLNK(s.st_mode)) {
                    symbol = '@';
                } else if ((S_ISREG(s.st_mode)) && (s.st_mode & S_IXUSR)) {
                    symbol = '*';
                } else {
                    symbol = ' ';
                }

                printf("%c", symbol);
            }

            if (listToggeled == 1){
                printf("\n");
            }
            else {
                printf("  ");
            }
        }
    }
    closedir(dir);
    return 0;
}

int main(int argc, char **argv) {
    int classifyToggeled = 0;
    int listToggeled = 0;
    char* dirToList = ".";

    if (argc == 1){
        listDir(dirToList, listToggeled, classifyToggeled);
        return 0;
    }
    for (int i = 1; i < argc; i++){
        char* currentArg = argv[i];

        //Check if -F is set
        if (strcmp(currentArg, "-F") == 0 || strcmp(currentArg, "-1F") == 0 || strcmp(currentArg, "-F1") == 0){
            classifyToggeled = 1;
        }

        //Check if -1 is set
        if (strcmp(currentArg, "-1") == 0 || strcmp(currentArg, "-1F") == 0 || strcmp(currentArg, "-F1") == 0){
            listToggeled = 1;
        }

        //List out all folders
        if (currentArg[0] != '-'){
            dirToList = currentArg;
        }

    }
    //If no folders were listed yet, list current folder
    //printf("dirtolist: %s", dirToList); <-- This line
    listDir(dirToList, listToggeled, classifyToggeled);
    if (listToggeled == 0){
        printf("\n");
    }
    return 0;
}

It has a few bugs:

  • When the printf line marked above is not commented out, the program tells realloc(): invalid old size
  • When this line is commented out this only happens if the program is executed without any parameters
  • /bin/ and /sbin/ print out weird characters

I think this is some kind of memmory issue but I have hardly any C knowledge to just see it

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

Your code exhibits undefined behaviour because you passed a non-static, uninitialised pointer to realloc whose contents were indeterminate.

From C11, Memory Management Functions:

The realloc function deallocates the old object pointed to by ptr and
returns a pointer to a new object that has the size specified by size.
….if ptr does not match a pointer earlier returned by a memory
management function, or if the space has been deallocated by a call to
the free or realloc function, the behavior is undefined.


Possible fixes:

  • Initialize it with 0 / NULL.
  • Declare it as static
  • Replace it with a call to malloc.

The realloc function returns a pointer to the new object (which may
have the same value as a pointer to the old object), or a null pointer
if the new object could not be allocated.

realloc returns NULL on failure, your code should check for it.

#include <errno.h>

char *line = 0;
errno = 0;

char *new = realloc (line, size);
if (!new) {
    perror ("realloc");
    /* realloc() failed to allocate memory, handle error accordingly. */
}

The above code snippet can be rewritten as:

#include <errno.h>

errno = 0;

char *new = malloc (size);
if (!new) {
    perror ("malloc");
    /* malloc() failed to allocate memory, handle error accordingly. */
}


Similarly, opendir returns a NULL pointer while lstat returns -1 to indicate an error. Check for them.


[1] — Objects declared with static storage duration and are always initialised. In the absence of a definition, they are implicitly initialised to 0.

From the C standard C11 6.7.9/10:

"… If an object that has static or thread storage duration is not
initialized explicitly, then:

if it has pointer type, it is initialized to a null pointer;

— if it has arithmetic type, it is initialized to (positive or
unsigned) zero;"

Though, it’s good practice to explicitly set it to 0.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading