【问题标题】:*** glibc detected *** free(): invalid pointer*** 检测到 glibc *** free(): 无效指针
【发布时间】:2013-08-01 12:48:31
【问题描述】:

我有以下代码,每当我运行代码时都会产生*** glibc detected *** free(): invalid pointer 错误。

main.h:

#ifndef PTHREAD_CALC_H_
#define PTHREAD_CALC_H_

void* task(void*);

#endif

main.cxx:

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <pthread.h>
#include "main.h"

int main(int argc, char* argv[]) {

    pthread_t *threads = (pthread_t*)malloc(sizeof(pthread_t)*2);
    double  *temp;

    double sum = 0.0;
    for (int j = 0; j < 2; j++) {
        pthread_create(&(threads[j]), NULL, task, NULL);
    }

    for (int j = 0; j < 2; j++) {
        pthread_join(threads[j], (void**)(&temp));
        sum += *temp;
    }

    free(threads);
    free(temp);

    return 0;
}

void* task(void *data) {
    double sum = 5;
    pthread_exit((void*)&sum);
    return NULL;
}

我很难确定是什么导致了错误。非常感谢任何帮助。如果我可以提供任何其他信息来帮助查明问题,请告诉我。

谢谢

编辑

为了完整起见,下面是按预期执行的结果代码:

main.cxx:

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <pthread.h>
#include "main.h"

int main(int argc, char* argv[]) {

    pthread_t *threads = (pthread_t*)malloc(sizeof(pthread_t)*2);
    double  *temp;

    double sum = 0.0;
    for (int j = 0; j < 2; j++) {
        pthread_create(&(threads[j]), NULL, task, NULL);
    }

    for (int j = 0; j < 2; j++) {
        pthread_join(threads[j], (void**)&temp);
        sum += temp;
        delete temp;
    }

    free(threads);
    return 0;
}

void* task(void *data) {
    double* sum = new double;
    *sum = 5.0;
    pthread_exit(static_cast<void*>(sum));
}

【问题讨论】:

  • 不相关,但您正在传回对 sum 的引用,但 sum 在堆栈上。将它添加到 main 中的 sum 变量时,此变量可能不存在。
  • @MWB 这不是pthread_join() 的重点吗?它阻塞父线程,直到任务完成。这让我相信sum 应该存在并且它的值应该存储在temp
  • 来自手册页 (man7.org/linux/man-pages/man3/pthread_exit.3.html) retval 指向的值不应位于调用线程的堆栈中,因为该堆栈的内容在线程终止后未定义。
  • @MWB 我明白你的意思了。感谢您指出这一点。
  • @AlexBrooks 您在编辑后没有为 new 分配内存。

标签: c++ pointers pthreads free glibc


【解决方案1】:

目前你的线程任务在线程堆栈上返回一些值。当线程完成时,不能保证 *temp 会指向有效的东西。

因此在这次通话之后

pthread_join(threads[j], (void**)(&temp));

temp 指向线程中 sum 的旧位置,但如果线程完成,它就不再存在。并且使用它会导致未定义的行为。

然后你释放指向另一个堆栈上的双精度的 temp,但需要注意的是释放,因为堆栈分配在超出范围时会自动释放。

free(temp);

你可能想做的是:

void* task(void *data) {
    double* sum = new double;
    *sum = 5;
    pthread_exit(static_cast<void*>(sum) );
}

加入线程后进入main

delete temp;

【讨论】:

  • 在您的帮助下,我找到了解决方案。我将更新原始帖子以包含产生预期行为的代码。
  • @AlexBrooks 很高兴能提供帮助,但您不应该在帖子中更改太多代码,当您不断更新问题时,很难继续更新我的答案。
  • 当然可以。我只是不想让人们抱怨代码太长。我应该等到我生成了缩短的代码后再发布。下次我会记住这一点。
  • 哦,顺便说一句,我使用了 C++ new 不要将它与免费混合使用,正如我提到的那样使用删除。
【解决方案2】:

在您的代码中声明:

double  *temp;

你永远不会 malloc 到地址,但后来你释放它。这将产生错误。删除免费(临时),它应该可以工作。实际上,尽管您通过取消引用 *temp 而不使用存储引入了新错误。

【讨论】:

  • 哇,我觉得自己很笨……我不知道我是怎么错过的。谢谢你。现在我只需要弄清楚如何将总和值放入temp...
  • 这还不够,正如 MWB 在上面的 cmets 中指出的那样。正如目前所描述的,这将导致未定义的行为,因为 *temp 将指向线程堆栈上的一个变量。
  • 对。 OP 的代码在我的帖子之间更改了几次。 IIRC,原始帖子实际上为 temp 做了 malloc,但在 task() 和程序结束时将其释放。无论如何,所选答案对于当前给出的代码是正确的。
猜你喜欢
  • 2012-05-04
  • 1970-01-01
  • 1970-01-01
  • 2016-06-16
  • 1970-01-01
  • 2016-03-27
  • 2016-03-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多