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

Memory leak that occurs when parsing commands separated by pipe(|)

I’m writing a shell with C.This shell max receives and executes the command separated by 20 pipes(|).The commands work smoothly, but when I do a memory check with Valgrind, I get the output as follows :

==64422== HEAP SUMMARY:
==64422==     in use at exit: 24 bytes in 1 blocks
==64422==   total heap usage: 9 allocs, 13 frees, 4,156 bytes allocated
==64422== 
==64422== 24 bytes in 1 blocks are definitely lost in loss record 1 of 1
==64422==    at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==64422==    by 0x491260E: strdup (strdup.c:42)
==64422==    by 0x1098C5: split_commands (in /home/furkan/MasaĂĽstĂĽ/hw02/my)
==64422==    by 0x109C93: main (in /home//MasaĂĽstĂĽ/hw02/my)
==64422== 
==64422== LEAK SUMMARY:
==64422==    definitely lost: 24 bytes in 1 blocks
==64422==    indirectly lost: 0 bytes in 0 blocks
==64422==      possibly lost: 0 bytes in 0 blocks
==64422==    still reachable: 0 bytes in 0 blocks
==64422==         suppressed: 0 bytes in 0 blocks
==64422== 
==64422== For lists of detected and suppressed errors, rerun with: -s
==64422== ERROR SUMMARY: 11 errors from 8 contexts (suppressed: 0 from 0)

In this part of the code, I parse the commands separated by pipe(|).Then I remove the gaps found at the beginning and end with strtrim. Valgrind says that there is a Memory leak in this part.However, I couldn’t figure out why the strdup() function creates a memory leak and how to block this leak.

char *strtrim(char *str) {
char *end;

// Trim leading space
while (isspace(*str)) {
    str++;
}

if (*str == 0) {  // All spaces?
    return str;
}

// Trim trailing space
end = str + strlen(str) - 1;
while (end > str && isspace(*end)) {
    end--;
}

// Write new null terminator
*(end+1) = 0;

return str;
}

void split_commands(char *input, char **commands, int *num_commands) {
    int count = 0;
    const char delimiter[] = "|";
    char *token;
   

    // Count the number of commands
    for (int i = 0; input[i]!= '\0'; i++) {
        if(input[i] == '|')
           count++;
    }
    *num_commands = count + 1;

   

    // Split input into commands
    token = strtok(input, delimiter);
    for (int i = 0; i < *num_commands; i++) {
        (commands)[i] = strtrim(strdup(token));

        token = strtok(NULL, delimiter);
    }
}

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 :

The memory leak occurs because you’re using strdup() to create a new copy of the token, and then passing it to strtrim() function. strtrim() function returns a pointer to the same memory block, but possibly with a different starting address. However, the original memory allocated by strdup() is never freed.

To fix the memory leak, you need to ensure that you free the memory allocated by strdup() once you no longer need it. You can do this by modifying the split_commands() function as follows:

void split_commands(char *input, char **commands, int *num_commands) {
    int count = 0;
    const char delimiter[] = "|";
    char *token;
    char *trimmed_token;

    // Count the number of commands
    for (int i = 0; input[i]!= '\0'; i++) {
        if(input[i] == '|')
           count++;
    }
    *num_commands = count + 1;

    // Split input into commands
    token = strtok(input, delimiter);
    for (int i = 0; i < *num_commands; i++) {
        trimmed_token = strtrim(strdup(token));
        (commands)[i] = strdup(trimmed_token);  // Create another copy of the trimmed string
        free(trimmed_token); // Free the memory allocated by strdup(token)

        token = strtok(NULL, delimiter);
    }
}

This ensures that the memory allocated by strdup(token) is freed after it has been trimmed, and the trimmed string is copied into commands[i].

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