释放指向指针结构的指针

时间:2012-12-25 00:07:05

标签: c multithreading memory-management malloc

我的情况似乎无法解决。它导致了一个缓慢的,但随着时间的推移,灾难性的内存泄漏。我注意到即使我释放了一个指针结构(我传递给了一个函数),我忘了释放它们内部的指针,这根据valgrind导致内存泄漏。我试图从函数中释放指针的内存,但我似乎无法解决错误消息error: request for member 'xxx' in something not a structure or union

这是我的计划的简短概述。我正在创建一个包含线程函数所需变量的数据结构。有一个main函数,其中传递参数,并根据它填充适当结构的数据。然后它启动实际函数的一个线程(将结构作为void指针传递),我在其中重新创建函数内部的实际结构。这是代码:

void cmd_test(char *sender, char **args, int arg_count) {
    char command[1024];

    // creates my exec pointer structure
    exec_struct *exec = malloc(sizeof(exec_struct));

    // adds a thread identifier to a struct to keep track of threads
    exec->tID = thread_add(EXEC);

    // the first malloc which I don't know how to free
    exec->sender = malloc(sizeof(char) * strlen(sender) + 1);
    sprintf(exec->sender, "%s", sender);

    // move ahead 5 arguments (there will always be 5 or more arguments supplied
    // by the calling function)
    args += 5;
    memset(command, 0, sizeof(command));

    // concatenate the remaining arguments into a cstring
    while(*args[0]) {
        printf("arg: %s\n", *args);
        sprintf(command, "%s %s", command, *args);
        args++;
    }

    // the second malloc which I don't know how to free
    exec->exec = malloc(sizeof(char) * strlen(command) + 1);

    // copy the string to the structure from pointer+1 to end of pointer
    // removes a space created from the first iteration of previous loop)
    sprintf(exec->exec, "%s", command + 1);

    printf("command:%s\n exec:%s\n", command, exec->exec);

    //stores an actual thread id into a struct of threads to keep track of 
    //the actual thread (other one is just to keep track of what type
    //of thread is running)
    threads[exec->tID].tID = Thread_Start(exec_cmd, exec);
}

这就是我如何设置我的结构,并对正在发生的事情发表一些评论。 Thread_Start()只是一个接受函数地址和结构地址以传递给线程函数的函数。这是exec_cmd函数:

void *exec_cmd(void *param) {
    char buf[1024];
    FILE *command;

    // recreate the structure locally inside the thread
    exec_struct exec = *((exec_struct *)param);

    // causes the error described
    // free(param.exec);
    // free(param.sender);

    // free the structure memory from the thread creating function.
    free(param);

    memset(buf,0,1024);
    sprintf(buf,"%s",exec.exec);
    command = popen(buf,"r");

    while(!feof(command)) {
        memset(buf,0,1024);
        fgets(buf,1024,command);
        printf("%s\n", buff);
        sleep(1);
    }

    pclose(command);

    // cleans itself up from the tracking structures
    thread_remove(EXEC, 0);

    // exits cleanly
    return NULL;
}

要解决错误,我试图在其前面强制转换结构,但错误仍然存​​在。使用->运算符会导致void* deference错误。

我还从函数中删除了一些批量,例如检查线程是否已经运行以及错误检查以减少混乱。这些函数都可以在我的应用程序中运行(它创建的线程存储得很好,它正在传递并完美地创建新结构并且它正在执行传递的命令)。只是我无法弄清楚如何释放我在线程内部进行的两个malloc调用。我该如何解决这个问题?

2 个答案:

答案 0 :(得分:2)

exec_struct exec = *((exec_struct *)param);

//free(param.exec);
//free(param.sender);

param是传入的void *。您的结构副本称为exec

你或许意味着:

free(exec.exec);
free(exec.sender);

但请注意,您稍后会在同一功能中立即访问exec.exec。如果你已经免费,你不能这样做。复制结构并不意味着你已经复制了指针所指向的内存。

这一行:

sprintf(buf,"%s",exec.exec);

exec.exec免费之前需要发生。

答案 1 :(得分:0)

一般原则是你从结构中的“最深”层面开始,然后继续前进。永远不要让“上层”的东西被释放,直到它内部的一切都被释放。换句话说,使用您调用malloc的相反顺序。

我真的没有注意到这一点:

exec_struct exec = *((exec_struct *)param);

我只想复制原始指针:

exec_struct *exec = (exec_struct *)param;

然后

free(exec->sender); 
free(exec->command);

free(exec);

当然,在完成exec结构的使用之前,不应该进行任何释放。