【问题标题】:Error in malloc while trying to create a thread尝试创建线程时 malloc 出错
【发布时间】:2018-04-26 13:03:23
【问题描述】:

大家好,我只发布产生问题和使用线程的代码的核心。

#define HR_OFF h_r-1
pthread_t *threads = NULL;
int h_r = 1;
int foo(int handler)
{
    // if everything is empty alloc resources
    if (threads == NULL) {
        threads = (pthread_t*)malloc(sizeof(pthread_t));
        // stuff with other variables
        h_r++;
    }
    else {
        // stuff with other variables
        threads = (pthread_t*)realloc(threads, sizeof(pthread_t) * h_r);
        h_r++;
    }

    // stuff with other variables
    register unsigned int counter = 0;
    while (pthread_create(&threads[HR_OFF], NULL, (void*)&foo2, NULL) != 0) {
        if (counter == MAX_TRYING) {
            fprintf(stderr, "THREAD_ERROR_C occurs \n");
            return THREAD_ERROR_C;
        }
    }
    return 0;
}

int foo2(void *data)
{
    // stuff with other variables
}

我们可以看到 foo 函数创建新线程并重新分配内存来存储 pthread_t。然后它尝试创建一个新线程,其中 pthread_create 为 NULL,attr 和 arg 为 NULL,函数指针为指向 foo2 的指针;

现在的问题是,当我执行代码时,我在调用 pthread_create 时出现内存分配错误并创建此错误消息:

  Program received signal SIGABRT, Aborted.
__GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
      ../sysdeps/unix/sysv/linux/raise.c: File o directory non esistente.

如果使用 gdb 进行打印回溯

#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1  0x00007ffff78513fa in __GI_abort () at abort.c:89
#2  0x00007ffff78939c8 in __malloc_assert (
    assertion=assertion@entry=0x7ffff7983088 "(old_top == initial_top (av) && old_size == 0) || ((unsigned long) (old_size) >= MINSIZE && prev_inuse (old_top) && ((unsigned long) old_end & (pagesize - 1)) == 0)", file=file@entry=0x7ffff797f867 "malloc.c", line=line@entry=2406, function=function@entry=0x7ffff79838d0 <__func__.11275> "sysmalloc") at malloc.c:301
#3  0x00007ffff7895546 in sysmalloc (nb=nb@entry=288, av=0x7ffff7bb6b00 <main_arena>) at malloc.c:2403
#4  0x00007ffff789642d in _int_malloc (av=av@entry=0x7ffff7bb6b00 <main_arena>, bytes=bytes@entry=272) at malloc.c:3865
#5  0x00007ffff7898b4b in __libc_calloc (n=<optimized out>, elem_size=<optimized out>) at malloc.c:3274
#6  0x00007ffff7deaf42 in allocate_dtv (result=result@entry=0x7ffff781c700) at dl-tls.c:322
#7  0x00007ffff7deb8ce in __GI__dl_allocate_tls (mem=mem@entry=0x7ffff781c700) at dl-tls.c:539
#8  0x00007ffff7bc400c in allocate_stack (stack=<synthetic pointer>, pdp=<synthetic pointer>, attr=0x7fffffffe4b0) at allocatestack.c:580
---Type <return> to continue, or q <return> to quit---
#9  __pthread_create_2_1 (newthread=0x55555575b4c8, attr=<optimized out>, start_routine=0x5555555564fd <pthread_fetcher_function>, arg=0x0) at pthread_create.c:539

我该如何解决这个问题,问题出在哪里。

感谢大家的耐心和对不起我的英语

【问题讨论】:

  • 你为什么要投射mallocstackoverflow.com/questions/605845/…
  • HR_OFF 是什么?为什么h_r 的开头是 1 而不是 0。
  • 我确定这不在该代码中,因为我使用其他变量做其他事情,这些变量不是 pthread_create 的参数,这是引发错误的地方
  • #define HR_OFF h_r-1 是一个特别有问题的宏,原因有几个。首先,它引用了一个不相关的符号h_r,它可以在宏展开的时候保持任何值。如果您的意图是创建一个常量,那么要么定义一个常量字面量宏,要么创建一个实际的常量(即const int MAX_THREADS = 1)。如果它应该是h_r 的函数,那么至少通过创建一个函数宏使其明确:#define HR_OFF(x) ((x) - 1)
  • 和往常一样,创建一个没有括号的宏总是一个坏主意。如果您在代码中的某处写了HR_OFF * 2,它会扩展为h_r - 1 * 2,这与(h_r - 1) * 2 完全不同。

标签: c linux multithreading malloc


【解决方案1】:

您的线程分配代码毫无意义,因为您只有 1 个线程句柄并且访问它threads[HR_OFF] 可能超出范围。强制转换 (void) * &amp;foo2 也是错误的,因为 foo2 具有应有的正确签名。在循环内重试失败的线程创建也不是一个好主意。请注意,此循环实际上是无限的,因为您永远不会增加 counter。在决定重试之前,您至少应该检查失败原因。

【讨论】:

  • 对不起,我没有写 HR_OFF 是一个定义为 h_r-1 的宏,所以它没有越界
  • @P.Carlino 那么它实际上肯定是越界了,因为它会评估为1,而最后一个(也是第一个)有效索引是0。请注意,您正在递增 h_r,因此此时它等于 2
  • @P.Carlino 是的。如果h_r 从 1 开始,然后将其递增,则为 2。2 减 1 为 1。1 是 second 条目的索引(第一个索引为零)。所以你有一个条目,你尝试使用第二个条目。哎呀。
猜你喜欢
  • 1970-01-01
  • 2015-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-05
  • 2017-02-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多