【问题标题】:Memory error and leaks with detached and exited thread?分离和退出线程的内存错误和泄漏?
【发布时间】:2015-10-05 04:08:03
【问题描述】:

我创建了一个简单的程序,它使用线程解析日志文件并打印一个值。在阅读了creating detached threads 之后,我在我的主函数中使线程分离并销毁了属性(PTHREAD_CREATE_DETACHED)。我还退出了线程(不退出会造成更多的内存泄漏)。但是,我仍然有内存泄漏和错误,即使我很确定我不会在程序的其余部分中 malloc 任何东西。完整代码如下:

*感谢 Jonathan Leffler 解析分隔字符串的 strtok_fixed 函数

static char *strtok_fixed(char *str, char const *delims)
{
    static char  *src = NULL;
    char  *p,  *ret = 0;

    if (str != NULL)
        src = str;

    if (src == NULL || *src == '\0')    // Fix 1
        return NULL;

    ret = src;                          // Fix 2
    if ((p = strpbrk(src, delims)) != NULL)
    {
        *p  = 0;
        //ret = src;                    // Unnecessary
        src = ++p;
    }
    else
        src += strlen(src);

    return ret;
}

void * parse_log(void *arguments){

    file = fopen("oms_requests.log", "r");
    char c;

    if (file == NULL){                        //no valid file
        printf("couldn't find the file\n");
    } else {
        int f = fseek(file, -2, SEEK_END);
        if (f == 0){
            int counter = 1;
            c = fgetc(file);
            while (c != '\n'){
                counter++;
                fseek(file, -counter, SEEK_END);
                c = fgetc(file);
            }

            //now read last line in the log into buff 
            char buff[counter];
            int l = fread(buff, 1, counter, file);
            buff[counter-1] = '\0';

            if (l != counter-1){
                printf("counter is wrong\n");
            } else {
                //skip over 22 commas to get the value that I want 
                char *buffer = strtok_fixed(buff, ",");
                for (int i = 0; i < 22; i++){
                    buffer = strtok_fixed(NULL, ",");
                    if (buffer == '\0') i++;
                        printf("%s\n", buffer);
                    }
                    printf("%ld\n", strtol(buffer, NULL, 10));
                }
        } else {
            printf("error in getting to bottom of file\n");
        }
    }
    fclose(file);
}


int main(int argc, char *argv[])
{
    //create pthread attributes and set to detached 
    pthread_t thr;
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

    int l = pthread_create(&thr, &attr, parse_log, NULL);
    if (l != 0){
        printf("Didn't work\n");
        return -1;
    }

    //destroy pthread attribute and exit 
    pthread_attr_destroy(&attr);
    pthread_exit(&thr);
    return 0;
}

这是我运行程序时 valgrind 给出的报告:

==12387== HEAP SUMMARY:
==12387==     in use at exit: 272 bytes in 1 blocks
==12387==   total heap usage: 7 allocs, 6 frees, 2,510 bytes allocated
==12387==
==12387== Searching for pointers to 1 not-freed blocks
==12387== Checked 8,486,312 bytes
==12387==
==12387== 272 bytes in 1 blocks are possibly lost in loss record 1 of 1
==12387==    at 0x4C2CC70: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==12387==    by 0x4012E54: _dl_allocate_tls (dl-tls.c:296)
==12387==    by 0x4E3FDA0: pthread_create@@GLIBC_2.2.5 (allocatestack.c:589)
==12387==    by 0x400E11: main (in /afs/.ir.stanford.edu/users/d/i/dianale/CS107/assign1a/reassemble)
==12387==
==12387== LEAK SUMMARY:
==12387==    definitely lost: 0 bytes in 0 blocks
==12387==    indirectly lost: 0 bytes in 0 blocks
==12387==      possibly lost: 272 bytes in 1 blocks
==12387==    still reachable: 0 bytes in 0 blocks
==12387==         suppressed: 0 bytes in 0 blocks
==12387==
==12387== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

我也尝试过 pthread_detach(&thr) 而不是设置属性(我也尝试过同时拥有两者),但我仍然遇到完全相同的内存泄漏和错误。有没有什么办法解决这一问题?

【问题讨论】:

  • 你如何编译这个?您使用 gcc 选项 -pthread 还是使用 -lpthread 的“just”链接??
  • 在thr这里传递pthread_exit(&amp;thr);背后的想法是什么?
  • 我在编译时专门在命令行中写了gcc -pthread -std=c99 -o file file.c,我没有收到任何错误或警告。我还认为我需要在pthread_exit 中指定要退出的确切线程,所以我将 &thr 放在那里。我也尝试过 pthread_exit(NULL) 并得到完全相同的内存错误/泄漏。
  • 总是在所有警告打开的情况下编译。为此,请使用 gcc 指定 -Wall -Wextra -pedantic。此外,您可能想查看pthread_exit() 的文档以了解该参数的用途。猜测是一个糟糕的选择......真的。
  • 感谢您提供有关警告的提示!我摆脱了所有警告,并且阅读了 pthread_exit() 文档。根据我的理解,在我的 parse_log 函数底部添加 return NULL 应该在 thr 上隐式调用 pthread_exit() 并结束线程。我认为 pthread_exit 应该在您可能有一个线程等待子线程的状态时使用,并且 pthread_exit 结束子线程,使其可供父线程使用。所以,我添加了return NULL 并删除了pthread_exit(),但我得到了更多的泄漏。我是不是误会了什么?

标签: c memory memory-management memory-leaks pthreads


【解决方案1】:

Pthreads 分配一定数量的内存来维护每个线程的内部状态。分离一个线程只标志着这些资源可以在线程退出后立即回收(而不是保持状态以防其他线程可能需要它)。 Butt 这些资源将保持分配状态,直到线程完成执行。 Valgrind 可能会将它们报告为可能的“泄漏”。

还请记住,valgrind 有时会报告误报。我也没有在您的代码中看到任何可能导致泄漏的明显内容。所以我不会担心那些“可能泄漏”的消息。

【讨论】:

  • 这个错误仍然有点令人不安;这表明我正在写一些我不应该写的东西。这也可以忽略吗?
  • 如果这是产生这些警告的代码,那么是的,我会忽略它。我看不到任何可能泄漏的东西。
猜你喜欢
  • 2020-12-04
  • 2014-06-08
  • 2016-10-02
  • 1970-01-01
  • 2011-11-05
  • 1970-01-01
  • 1970-01-01
  • 2022-06-16
  • 2011-09-18
相关资源
最近更新 更多