簡體   English   中英

在C中動態分配線程

[英]Dynamically allocating threads in C

我正在用C創建一個小程序,該程序將計算用戶輸入的數字,直到用戶輸入負數。 它使用線程來做到這一點。

我在運行時遇到分段錯誤,所以我做錯了什么,但我不知道到底是什么。

這是我的代碼:

/* 
 * File:   main.c
 * Author: thomasvanhelden
 *
 * Created on June 15, 2014, 3:17 AM
 */

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

/**
 * Calculates faculty of given number
 *      Can run as a thread
 * @param param The given number
 * @return Doesn't return anything
 */
void *fac(void *param) {
    int* number = (int*) param;
    int faculty = 1;
    int i; // counter

    printf("De faculteit van %i is: ", number);

    for (i = 2; i <= number; i++) {
        faculty *= i;
    }

    printf("%i\n", faculty);
}

/*
 * 
 */
int main(int argc, char** argv) {
    pthread_t **threads; 
    int getal, numThreads = 0, counter, stop = 0;

    // ask for numbers until user enters negative number
    while (stop == 0) {
        scanf("%i", getal);

        if (getal >= 0) {
            numThreads++;
            threads = realloc(threads, sizeof(pthread_t*) * (numThreads+1));
            threads[numThreads - 1] = malloc(sizeof(pthread_t));

            // Create the thread
            if (pthread_create(&threads[numThreads - 1], NULL, fac, &getal)) {
                // something went wrong
                printf("Error creating thread %i!\n", numThreads);
                return 1;
            }

        } else {
            // User entered negative number and wants to stop
            stop = 1;
        }
    }

    // join all the threads
    for (counter = 0; counter < numThreads; counter++) {
        if (pthread_join(threads[counter], NULL)) {
            printf("Something went wrong joining thread %i\n", counter + 1);
        }
    }


    return (EXIT_SUCCESS);
}

我認為您的意思是“階乘”? 無論如何,您的代碼存在多個問題。 即使沒有啟用嚴格的標志,我也會收到以下警告:

fac.c:23:40: warning: format specifies type 'int' but the argument has type 'int *' [-Wformat]
    printf("De faculteit van %i is: ", number);
                             ~~        ^~~~~~
fac.c:25:19: warning: ordered comparison between pointer and integer ('int' and 'int *')
    for (i = 2; i <= number; i++) {
                ~ ^  ~~~~~~
fac.c:30:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
fac.c:41:21: warning: format specifies type 'int *' but the argument has type 'int' [-Wformat]
        scanf("%i", getal);
               ~~   ^~~~~
fac.c:49:32: warning: incompatible pointer types passing 'pthread_t **' (aka 'struct _opaque_pthread_t ***') to
      parameter of type 'pthread_t *' (aka 'struct _opaque_pthread_t **'); remove &
      [-Wincompatible-pointer-types]
            if (pthread_create(&threads[numThreads - 1], NULL, fac, &getal)) {
                               ^~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/pthread.h:310:42: note: passing argument to parameter here
int pthread_create(pthread_t * __restrict, const pthread_attr_t * __restrict,
                                         ^
fac.c:63:26: warning: incompatible pointer types passing 'pthread_t *' (aka 'struct _opaque_pthread_t **') to
      parameter of type 'pthread_t' (aka 'struct _opaque_pthread_t *'); dereference with *
      [-Wincompatible-pointer-types]
        if (pthread_join(threads[counter], NULL)) {
                         ^~~~~~~~~~~~~~~~
                         *
/usr/include/pthread.h:333:28: note: passing argument to parameter here
int pthread_join(pthread_t , void **) __DARWIN_ALIAS_C(pthread_join);
                           ^
6 warnings generated.

實際上,如果您在gdb下運行該程序,則在輸入數字后它會崩潰:

...
4

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x0000000000000000
0x00007fff92c1401a in __svfscanf_l ()
(gdb) bt
#0  0x00007fff92c1401a in __svfscanf_l ()
#1  0x00007fff92c0c0eb in scanf ()
#2  0x0000000100000d72 in main (argc=1, argv=0x7fff5fbffa18) at fac.c:41

查看帶有bt的堆棧跟蹤,我們立即看到它在第41行調用scanf()崩潰。 而且,如果您回顧一下編譯器警告,它告訴您它期望一個int*但您只傳遞了一個int 這是因為scanf需要一個指針才能使用用戶輸入來修改變量。

如果您修復了所有其余的警告,則代碼將起作用。

  • 您需要取消引用numberfac ,當你想它的價值功能
  • 您需要將threads初始化為NULL以便realloc可以工作(否則它是未定義的,大概是非零的,因此永遠不會(重新)分配緩沖區)
  • pthread_createpthread_join調用需要更新,因此值/指針與期望的簽名匹配

完成上述更改后,我可以按預期運行它:

$ ./fac_fixed
3
De faculteit van 3 is: 6
4
De faculteit van 4 is: 24
5
De faculteit van 5 is: 120
6
De faculteit van 6 is: 720
7
De faculteit van 7 is: 5040
8
De faculteit van 8 is: 40320
9
De faculteit van 9 is: 362880
12
De faculteit van 12 is: 479001600
-1

至於代碼的結構,我不明白為什么仍然要創建一個線程數組,因為您一次只能按順序計算一個線程。 您實際上只需要最多一個工作線程,但是由於main除了執行阻塞操作外什么也沒做,因此它實際上並不需要在線程中。 但是至少它不會崩潰!

第一次調用realloc()時,應將threads設置為NULL。 實際上,您正在傳遞未定義的行為 ,即未定義的指針。

1)初始化為0:

pthread_t **threads = 0; 

2)您還在打印指針,而不是它們指向的指針:

printf("De faculteit van %i is: ", *number);

3)scanf()需要&期望%dint *

scanf("%i", &getal);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM