LPTHREADS:指向结构的结构或地址的指针?

时间:2018-04-20 06:36:22

标签: c memory-management pthreads

我有一个创建N个进程的程序,每个进程都创建M个线程。

我还有一个需要传递给线程函数的结构。

当我像这样创建M个线程时:

thread_args_t** thread_arg = malloc(sizeof(thread_args_t*)*m);
for(int i=0;i<m;i++)
{
    thread_arg[i] = malloc(sizeof(thread_args_t));
    thread_arg[i]->child_id = child_id;
    thread_arg[i]->thread_id = i;

    pthread_create(&threads[i], NULL, thread_function, thread_arg[i]);
}

该计划完美无缺。

但是,如果我创建了一个这种结构的数组并且我传递了数组的地址,那么该程序不起作用:

thread_args_t* thread_arg = malloc(sizeof(thread_args_t)*m);
for(int i=0;i<m;i++)
{
    thread_arg[i].child_id = child_id;
    thread_arg[i].thread_id = i;

    pthread_create(&threads[i], NULL, thread_function, &thread_arg[i]);
}

这是线程进程代码:

void* thread_function(void* x)
{
    thread_args_t *args = (thread_args_t*)x;

    /* TODO: protect the critical section using semaphore(s) as needed */

    //Do stuff

    free(x);
    pthread_exit(NULL);
}

那么,这里有什么问题?

我在thread_function谈到无效指针时遇到运行时错误 这是输出屏幕:

(我注意到错误类型并不总是相同)

> [Main] Initializing file accesses.log...closed...file correctly initialized!!!
[Main] Creating named semaphore /sem_cs...Done /sem_cs: 1
[Main] Creating named semaphore /sem_ready...Done /sem_ready: 0
[Main] Creating named semaphore /sem_start...Done /sem_start: 0
[Main] Creating named semaphore /sem_closed...Done /sem_closed: 0
mainProcess All are ready. Firing. BAAAAAANG!
mainProcess RONFRONF
Child N.4 bursting 10 threads
Child N.0 bursting 10 threads
Child N.1 bursting 10 threads
Child N.2 bursting 10 threads
[Child#1-Thread#2] File accesses.log opened in append mode!!!
[Child#1-Thread#2] 1 appended to file accesses.log opened in append mode!!!
[Child#1-Thread#2] File accesses.log closed!!!
Child N.3 bursting 10 threads
[Child#0-Thread#0] File accesses.log opened in append mode!!!
*** Error in `./riepilogo_errato': double free or corruption (out): 0x0000000001c18640 ***
[Child#0-Thread#0] 0 appended to file accesses.log opened in append mode!!!
[Child#0-Thread#0] File accesses.log closed!!!
======= Backtrace: =========
Child N.0 joining threads[0]
/lib/x86_64-linux-gnu/libc.so.6([Child#1-Thread#1] File accesses.log opened in append mode!!!
+0x777e5)[0x7f0ebaacf7e5]
[Child#1-Thread#1] 1 appended to file accesses.log opened in append mode!!!
[Child#1-Thread#1] File accesses.log closed!!!
/lib/x86_64-linux-gnu/libpthread.so.0[Child#4-Thread#0] File accesses.log opened in append mode!!!
*** Error in `./riepilogo_errato[Child#4-Thread#0] 4 appended to file accesses.log opened in append mode!!!
[Child#0-Thread#4] File accesses.log opened in append mode!!!
/lib/x86_64-linux-gnu/libc.so.6[Child#0-Thread#4] 0 appended to file accesses.log opened in append mode!!!
[Child#0-Thread#4] File accesses.log closed!!!
*** Error in `./riepilogo_errato': double free or corruption (out): 0x0000000001c18650 ***
[Child#2-Thread#0] File accesses.log opened in append mode!!!
[Child#2-Thread#0] 2 appended to file accesses.log opened in append mode!!!
======= Backtrace: =========
[Child#2-Thread#0] File accesses.log closed!!!
[Child#0-Thread#1] File accesses.log opened in append mode!!!
[Child#0-Thread#1] 0 appended to file accesses.log opened in append mode!!!
[Child#0-Thread#1] File accesses.log closed!!!
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f0ebaacf7e5]
[Child#4-Thread#0] File accesses.log closed!!!
[Child#2-Thread#1] File accesses.log opened in append mode!!!
[Child#2-Thread#1] 2 appended to file accesses.log opened in append mode!!!
[Child#2-Thread#1] File accesses.log closed!!!
Child N.2 joining threads[0]
[Child#4-Thread#9] File accesses.log opened in append mode!!!
[Child#4-Thread#9] 4 appended to file accesses.log opened in append mode!!!
[Child#4-Thread#9] File accesses.log closed!!!
[Child#3-Thread#0] File accesses.log opened in append mode!!!
[Child#3-Thread#0] 3 appended to file accesses.log opened in append mode!!!
[Child#3-Thread#0] File accesses.log closed!!!
Child N.3 joining threads[0]
[Child#3-Thread#1] File accesses.log opened in append mode!!!
[Child#3-Thread#1] 3 appended to file accesses.log opened in append mode!!!
[Child#3-Thread#1] File accesses.log closed!!!
*** Error in `./riepilogo_errato': free(): invalid pointer[Child#3-Thread#2] File accesses.log opened in append mode!!!
[Child#3-Thread#2] 3 appended to file accesses.log opened in append mode!!!
[Child#3-Thread#2] File accesses.log closed!!!
*** Error in `./riepilogo_errato[Child#3-Thread#7] File accesses.log opened in append mode!!!

2 个答案:

答案 0 :(得分:3)

您的线程代码释放传递的指针:

void* thread_function(void* x)
{
    thread_args_t *args = (thread_args_t*)x;

    free(x);  // <-- HERE
}

但是,这不是从分配函数返回的指针 - 它是数组中的指针。

那是未定义的行为。

此修复只是删除对free()的调用。

答案 1 :(得分:0)

据我所知(我最后一次使用pthreads有点陈旧),这里没有错。您的错误消息表明您多次尝试free malloc个内存。

因为你只是为每个线程使用一个分配的空间而不是每个线程的一个分配,我假设你在关闭每个线程后仍然尝试free。但如果没有MCVE,这将很难检查。

基本上你的第一个程序使用指针的“数组”。然后为每个指针分配内存。这些传递给你的线程。

int **arr = malloc(sizeof *arr *2);
arr[0] = malloc(sizeof **arr);
arr[1] = malloc(sizeof **arr);

现在你有三个分配他们必须自己释放。

free(arr[0]);
free(arr[1]);
free(arr); // this has to be the last or else you lose your reference for the other pointers.

第二个程序在我看来更好,你只需要获得一个参数数组(这可以减少碎片),你只需要释放一个分配。

int *arr = malloc(sizeof *arr *2);
...
free(arr);

但由于free是由另一个函数完成的(不是由你编写的),它可能需要第一个实现并尝试释放它,如上所示。哪个会尝试释放未分配的内存,导致您的错误。

关于你的编辑: 传递的参数在线程中获得free d。但是你的第二个参数没有分配那个内存单元(只是作为更大分配的一部分),产生了问题。