malloc里面的线程例程

时间:2016-08-30 22:57:10

标签: c pthreads malloc

以下代码摘录是否会导致一般问题:

void * fct(void * p)
{
  int i = 0;
  int * input = (int *) p;
  int * arr = malloc((*input)*sizeof(int));
  /* put something in arr */
  return (void *) arr
}

int main()
{
  /* prologue */
  for (i = 0; i < MAX_THREADS; i++)
  {
    rc = pthread_create(&threads[i], NULL, fct, (void *) &input[i]);
  }
  /* epilogue */
}

我实际上没有理解并且没有找到答案的是:线程例程(iinputarr)内的变量是否共享?我理解pthreads的方式是fct的不同副本被称为MAX_THREADS次,每个副本都有自己的一组变量。

3 个答案:

答案 0 :(得分:2)

全局变量在线程之间共享。对您作为参数传递的输入的引用也是如此。

另一方面,您所引用的变量是本地人,在堆栈上分配并且彼此不同。这与线程无关,而与堆栈指针的当前值无关。 malloc的结果也会有所不同,因为malloc被多次调用。

所有这些与线程的关系非常松散,并且在同一个线程中对函数的多次调用将在内存方面表现相同(不是按时间)。关于局部变量会有一些细微的差别,因为在线程之间不会共享堆栈。

您的代码无法编译。

答案 1 :(得分:1)

对您的问题的简洁回答&#34; ...代码摘录是否导致一般问题&#34;是&#34;不&#34;。正如各种评论和答案所述:

  

函数中的本地自动变量本质上是线程安全的;它们被重新分配给函数的每次调用,无论是在线程上下文中还是在递归上下文中,或者是对函数的简单调用。通常全局变量是共享的 - 除非创建为线程本地存储(TLS)或线程特定存储(TSS - C11中使用的术语)。代码[在问题中]应该是正常的,除了线程返回时的内存泄漏 - 但是线程清理代码没有显示,这可能是不公平的。您需要通过pthread_join()捕获返回值并释放它以避免泄漏。

将代码摘录充实到工作代码中,使用互斥锁显示并确保一次一个线程正在打印其数据,您可以使用以下代码:

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;

static void *fct(void *p)
{
    int number = *(int *)p;
    int *arr = malloc(number * sizeof(int));  // Error check missing!
    for (int i = 0; i < number; i++)
        arr[i] =  number + (7 * i + 5) % 11;
    pthread_mutex_lock(&mtx);   // Error check missing!
    printf("Integers %2d (%p):", number, (void *)arr);
    for (int i = 0; i < number; i++)
        printf(" %3d", arr[i]);
    putchar('\n');
    pthread_mutex_unlock(&mtx); // Error check missing!
    return (void *)arr;
}

enum { MAX_THREADS = 10 };

int main(void)
{
    pthread_t threads[MAX_THREADS];
    int input[MAX_THREADS];
    int *result[MAX_THREADS];

    /* Initialization */
    for (int i = 0; i < MAX_THREADS; i++)
        input[i] = (3 * i + 2) % 13 + 1;

    /* Thread creation */
    for (int i = 0; i < MAX_THREADS; i++)
    {
        pthread_mutex_lock(&mtx);   // Error check missing!
        printf("Launch %d: %2d\n", i, input[i]);
        pthread_mutex_unlock(&mtx); // Error check missing!
        int rc = pthread_create(&threads[i], NULL, fct, (void *)&input[i]);
        if (rc != 0)
        {
            fprintf(stderr, "Oops creating thread %d\n", i);
            exit(EXIT_FAILURE);
        }
    }

    /* Thread harvesting */
    for (int i = MAX_THREADS; i-- > 0; )
    {
        void *vp;
        int rc = pthread_join(threads[i], &vp);
        if (rc != 0)
        {
            fprintf(stderr, "Oops joining thread %d\n", i);
            exit(EXIT_FAILURE);
        }
        printf("Thread %d: %2d (%p)\n", i, input[i], vp);
        result[i] = vp;
    }

    /* Finalization */
    for (int i = 0; i < MAX_THREADS; i++)
    {
        printf("Master - %d:", i);
        for (int j = 0; j < input[i]; j++)
            printf(" %3d", result[i][j]);
        putchar('\n');
        free(result[i]);
    }

    pthread_mutex_destroy(&mtx);
    return 0;
}

运行示例

Launch 0:  3
Launch 1:  6
Launch 2:  9
Launch 3: 12
Integers  6 (0x7faf9ae01890):  11   7  14  10   6  13
Integers  3 (0x7faf9af00000):   8   4  11
Integers  9 (0x7faf9b800000):  14  10  17  13   9  16  12  19  15
Launch 4:  2
Integers 12 (0x7faf9b800030):  17  13  20  16  12  19  15  22  18  14  21  17
Launch 5:  5
Integers  2 (0x7faf9af00010):   7   3
Integers  5 (0x7faf9b800060):  10   6  13   9   5
Launch 6:  8
Launch 7: 11
Integers  8 (0x7faf9ae018b0):  13   9  16  12   8  15  11  18
Launch 8:  1
Integers 11 (0x7faf9b800080):  16  12  19  15  11  18  14  21  17  13  20
Launch 9:  4
Integers  1 (0x7faf9af00020):   6
Integers  4 (0x7faf9b8000b0):   9   5  12   8
Thread 9:  4 (0x7faf9b8000b0)
Thread 8:  1 (0x7faf9af00020)
Thread 7: 11 (0x7faf9b800080)
Thread 6:  8 (0x7faf9ae018b0)
Thread 5:  5 (0x7faf9b800060)
Thread 4:  2 (0x7faf9af00010)
Thread 3: 12 (0x7faf9b800030)
Thread 2:  9 (0x7faf9b800000)
Thread 1:  6 (0x7faf9ae01890)
Thread 0:  3 (0x7faf9af00000)
Master - 0:   8   4  11
Master - 1:  11   7  14  10   6  13
Master - 2:  14  10  17  13   9  16  12  19  15
Master - 3:  17  13  20  16  12  19  15  22  18  14  21  17
Master - 4:   7   3
Master - 5:  10   6  13   9   5
Master - 6:  13   9  16  12   8  15  11  18
Master - 7:  16  12  19  15  11  18  14  21  17  13  20
Master - 8:   6
Master - 9:   9   5  12   8

完全披露:

使用GCC 6.1.0和Valgrind 3.12.0.SVN在Mac OS X 10.11.6上测试。并且,当在Valgrind下运行时,它会崩溃。不在Valgrind下运行时不会崩溃。

==3412== Memcheck, a memory error detector
==3412== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==3412== Using Valgrind-3.12.0.SVN and LibVEX; rerun with -h for copyright info
==3412== Command: ./pth37
==3412== 
Launch 0:  3
Launch 1:  6
Launch 2:  9
Launch 3: 12
Launch 4:  2
Integers  3 (0x100aaf5b0):   8   4  11
Launch 5:  5
Integers 12 (0x100aaf600):  17  13  20  16  12  19  15  22  18  14  21  17
Integers  6 (0x100aaf670):  11   7  14  10   6  13
Integers  9 (0x100aaf6d0):  14  10  17  13   9  16  12  19  15
Integers  2 (0x100aaf740):   7   3
Launch 6:  8
Integers  5 (0x100aaf790):  10   6  13   9   5
Launch 7: 11
Integers  8 (0x100aaf7f0):  13   9  16  12   8  15  11  18
Launch 8:  1
Integers 11 (0x100aaf850):  16  12  19  15  11  18  14  21  17  13  20
Launch 9:  4
==3412== 
==3412== Process terminating with default action of signal 11 (SIGSEGV)
==3412==  Access not within mapped region at address 0x700003062C1A
==3412==    at 0x10046F374: _pthread_find_thread (in /usr/lib/system/libsystem_pthread.dylib)
==3412==    by 0x10046F2CF: _pthread_lookup_thread (in /usr/lib/system/libsystem_pthread.dylib)
==3412==    by 0x10047061A: pthread_join (in /usr/lib/system/libsystem_pthread.dylib)
==3412==    by 0x100000C3C: main (pth37.c:52)
==3412==  If you believe this happened as a result of a stack
==3412==  overflow in your program's main thread (unlikely but
==3412==  possible), you can try to increase the size of the
==3412==  main thread stack using the --main-stacksize= flag.
==3412==  The main thread stack size used in this run was 8388608.
--3412:0:schedule VG_(sema_down): read returned -4
==3412== 
==3412== HEAP SUMMARY:
==3412==     in use at exit: 26,557 bytes in 196 blocks
==3412==   total heap usage: 280 allocs, 84 frees, 32,789 bytes allocated
==3412== 

Memcheck: mc_leakcheck.c:1106 (void lc_scan_memory(Addr, SizeT, Bool, Int, Int, Addr, SizeT)): Assertion 'bad_scanned_addr >= VG_ROUNDUP(start, sizeof(Addr))' failed.

host stacktrace:
==3412==    at 0x238050773: ???
==3412==    by 0x238050B9C: ???
==3412==    by 0x238050B7A: ???
==3412==    by 0x238003B86: ???
==3412==    by 0x2380033A6: ???
==3412==    by 0x238002050: ???
==3412==    by 0x238014F0D: ???
==3412==    by 0x23805D562: ???
==3412==    by 0x2380F2772: ???
==3412==    by 0x2380F287A: ???

sched status:
  running_tid=2

我对此感到困惑,对此我很有礼貌。

答案 2 :(得分:0)

您正在做的事情导致问题。 pthread_create会返回错误代码。从手册页:

  

成功时,pthread_create()返回0;出错时,会返回错误   数字,*线程的内容未定义。

您无法以这种方式将指针返回malloc。您必须拥有一个全局指针数组,您的线程可以将其malloc结果保存在其中,或者您必须将指针作为参数传递。如果你想要传递给一个线程有多个参数,我知道如何做的唯一方法是使用struct