【问题标题】:Where is my memory leak not being freed in this shell simulation?在这个 shell 模拟中我的内存泄漏在哪里没有被释放?
【发布时间】:2021-12-14 20:54:26
【问题描述】:

我找不到在使用 valgrind 工具的 shell 模拟 C 程序中没有释放内存泄漏的地方。我还使用 gdb 调试器运行了我的程序。 writableUsersArgs 包含 "/usr/bin/vim" 作为第一个元素,NULL 作为第二个元素。使用调试器,它显示数组writableUsersArgs 被释放了两次。

包含内存泄漏的函数

int start(char* command){
        // pid uses status's value behind the scenes
        int status;
        int maxArgLength = 0;
        int argLength = 0;
        int index;

        // Split the user's command into seperate strings wherever the command has spaces
        char** usersArgs = commandDelimeter(command);
        int numberArgs = countArgs(command);
        // Calculate maxArgLength to allocate correct amount of memory
        for(index = 0; index < numberArgs; index++) {
                argLength = countLongestArg(usersArgs[index]);
                if(argLength > maxArgLength) {
                        maxArgLength = argLength;
                }
        }
        // Allocate memory for the array that gets passed to exec() function
        char* writableUsersArgs[numberArgs+1];
        for(index = 0; index < numberArgs + 1; index++) {
                writableUsersArgs[index] = (char*)malloc(maxArgLength*sizeof(char));
        }
        // Copy the strings from the read only array to a writable array of strings
        for(index = 0; index < numberArgs; index++) {
                strcpy(writableUsersArgs[index], usersArgs[index]);
        }
        // Last entry of array must be NULL for exec() function to work properly
        writableUsersArgs[index] = NULL;

        // Create a child process
        pid_t pid = fork();
        if(pid == -1) {
                printf("Error forking");
                return -1;
        } else if(pid == 0) {
                // Jumps into new child process
                execv(writableUsersArgs[0], writableUsersArgs);
                return 2;
        } else {
                // Waits for child process to terminate before proceeding
                wait(&status);
                for(index = 0; index < numberArgs + 1; index++) {
                        free(usersArgs[index]);
                        free(writableUsersArgs[index]);
                }
                free(usersArgs);
                return 1;
        }
}

Valgrind 内存检查错误信息

==670== HEAP SUMMARY:
==670==     in use at exit: 26 bytes in 2 blocks
==670==   total heap usage: 73 allocs, 71 frees, 8,432 bytes allocated
==670==
==670== 13 bytes in 1 blocks are definitely lost in loss record 1 of 2
==670==    at 0x483DD99: calloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==670==    by 0x10ABC3: createArgsArray (mysh.c:579)
==670==    by 0x10A946: commandDelimeter (mysh.c:508)
==670==    by 0x109DB0: start (mysh.c:269)
==670==    by 0x109820: executeCommandWithArgs (mysh.c:151)
==670==    by 0x109641: executeCommand (mysh.c:115)
==670==    by 0x109542: insideShell (mysh.c:83)
==670==    by 0x1094C3: main (mysh.c:63)
==670==
==670== 13 bytes in 1 blocks are definitely lost in loss record 2 of 2
==670==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==670==    by 0x109EDB: start (mysh.c:281)
==670==    by 0x109820: executeCommandWithArgs (mysh.c:151)
==670==    by 0x109641: executeCommand (mysh.c:115)
==670==    by 0x109542: insideShell (mysh.c:83)
==670==    by 0x1094C3: main (mysh.c:63)
==670==
==670== LEAK SUMMARY:
==670==    definitely lost: 26 bytes in 2 blocks
==670==    indirectly lost: 0 bytes in 0 blocks
==670==      possibly lost: 0 bytes in 0 blocks
==670==    still reachable: 0 bytes in 0 blocks
==670==         suppressed: 0 bytes in 0 blocks

【问题讨论】:

标签: c memory-leaks valgrind


【解决方案1】:

在start 中,您使用malloc 分配内存并将其分配给一个指针,然后您使用NULL 覆盖指针的内容。你现在已经忘记了malloced 的记忆。

所以,在这个循环中:

for(index = 0; index < numberArgs + 1; index++) {
    writableUsersArgs[index] = (char*)malloc(maxArgLength*sizeof(char));
}

writableUsersArgs 的每个成员都分配了一个指针,指向 malloc 保留的唯一内存块,包括数组成员 writableUsersArgs[numberArgs]。

几行之后,你写

writableUsersArgs[index] = NULL;

她的index 与numberArgs 具有相同的值。您现在已经丢失了对 writableUsersArgs[index] 之前指向的 malloced 块的所有引用。

您可能想在 index &lt; numberArgs 时运行循环。

这仅涉及start 中丢失的块。除非您显示该代码,否则我无法对 commandDelimeter 或 createArgsArray 中丢失的块说任何话。但我怀疑这是同样的问题。

最后只是一个注释:我认为在调用fork/exec之前不需要复制creareArgsArray返回的字符串

【讨论】:

    猜你喜欢
    • 2019-07-13
    • 2020-04-15
    • 1970-01-01
    • 2010-11-17
    • 2012-05-22
    • 2011-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多