1

私は、セマフォを実装する c のマルチスレッド プロデューサー/コンシューマー プログラムに取り組んでいます。各バッファ構造体には 2 つの一般的なセマフォがあります。1 つは空のバッファ用で、もう 1 つはフル バッファ用です。ただし、プログラムが readInput 関数に入ると、これら 2 つのセマフォの値はランダムな値に変わります。スレッド構造体内のセマフォは問題ありませんが、スレッド構造体内の IO ユニオン内のバッファ構造体内のセマフォが何らか​​の理由で変更されています。なぜこれが起こっているのですか?

#include "st.h"
#include "semaphore.h"
#include "buffer.h"

/*Definitions here*/
//Input location.
#define DEFAULT_IN stdin
//Output location.
#define DEFAULT_OUT stdout
//Line width
#define LINE_SIZE 80
#define SLEEP_TIME 333333

//Shorthand for structure components
#define INPUT thread->in
#define MUTEX thread->mutex
#define OUTPUT thread->out

/*Global variables here*/

//The input/output can be a stream or a buffer.
typedef union
{
    buffer *bufferIO;   //Buffer to read from/write to.
    FILE *stream;       //An I/O stream.
} IO;

//Each thread has an input, a semaphore, and an output.
typedef struct
{
        IO in;          //Either an input stream or a buffer to read.
        semaphore *mutex;   //Pointer to a binary semaphore.
        IO out;         //Either an output stream or a buffer to write.
} Thread;


/*Function prototypes here*/
void *readInput(void *s);
void *processLines(void *s);
void *processAsterisks(void *s);
void *writeOutput(void *s);

int main (int argc, char const *argv[])  //The main function  
{
    st_init();

    /*Binary semaphore*/
    semaphore mutex;        //Binary semaphore for mutual exclusion.
    createSem(&mutex, 1);

    printf("Beginning...\n");
    /*The three buffers between threads*/
    buffer B1, B2, B3;
    createBuf(&B1);
    createBuf(&B2);
    createBuf(&B3);

    /*The 5 data locations*/
    IO input, buffer1, buffer2, buffer3, output;    //stdin, 3 buffers, stdout

    /*Set the unions*/
    input.stream = DEFAULT_IN;  //Input stream
    buffer1.bufferIO = &B1;     //Contains raw input
    buffer2.bufferIO = &B2;     //Newlines have become spaces
    buffer3.bufferIO = &B3;     //** has become ^
    output.stream = DEFAULT_OUT;    //Output stream, 80 at a time

    /*Initialize the threads*/
        Thread input_thread = {input, &mutex, buffer1};         //Recieve input
        Thread proc1_thread = {buffer1, &mutex, buffer2};       //Returns to spaces
        Thread proc2_thread = {buffer2, &mutex, buffer3};       //** to ^
        Thread output_thread = {buffer3, &mutex, output};       //Output 80 characters and a newline.

    printf("%i\n", input_thread.out.bufferIO->emptyBuffers->value);
    /*Create the actual threads*/
    if(st_thread_create(readInput, &input_thread, 0, 0) == NULL)
    {
        perror("st_thread_create for input thread failure");
        exit(1);
    }
    printf("%i\n", input_thread.out.bufferIO->emptyBuffers->value);
    if(st_thread_create(processLines, &proc1_thread, 0, 0) == NULL)
    {
        perror("st_thread_create for line thread failure");
        exit(1);
    }
    if(st_thread_create(processAsterisks, &proc2_thread, 0, 0) == NULL)
    {
        perror("st_thread_create for asterisk thread failure");
        exit(1);
    }
    if(st_thread_create(writeOutput, &output_thread, 0, 0) == NULL)
    {
        perror("st_thread_create for output thread failure");
        exit(1);
    }

    st_thread_exit(NULL);
    return 0;
}
/*Function definitions here*/
void *readInput(void *s)
{
    Thread *thread = s;
    char c;                 //An individual character.

    printf("Type some input.\n");
    do
    {
        down(MUTEX);
        c = getc(INPUT.stream);     //Consume a character from input.
    printf("%i\n", OUTPUT.bufferIO->emptyBuffers->value);
        deposit(OUTPUT.bufferIO, c);    //Produce a character.
        up(MUTEX);
        st_usleep(SLEEP_TIME);      //Wait.
    }
    while(c != EOF);            //Do-while in order to pass on the EOF as an exit flag.

    //EOF reached - exit thread.
    //assert(c == EOF);

    printf("\nDone reading.");
    st_thread_exit(NULL);
}...

gdb で調べたところ、次のことがわかりました。

Hardware watchpoint 10: (*(*input_thread.out.bufferIO).emptyBuffers).value
(gdb) c
Continuing.
Hardware watchpoint 10: (*(*input_thread.out.bufferIO).emptyBuffers).value

Old value = 80
New value = 4216725
0x000000395221467c in _dl_runtime_resolve () from /lib64/ld-linux-x86-64.so.2

この _dl_runtime_resolve が何であるかわかりません。

4

1 に答える 1

0

セマフォとバッファはメイン スレッドでスタック変数として作成されるため、メイン スレッドが終了すると、セマフォとバッファを指すアドレスが無効になり、動作が予測できなくなります。適切な設計を行い、変数に適切なスコープを与えます。とりあえず、すべての変数をグローバルにします。上記のコードで次のことをグローバルにします

  1. セマフォミューテックス; //相互排除用のバイナリセマフォ。

  2. IO 入力、バッファ 1、バッファ 2、バッファ 3、出力。//stdin、3 つのバッファ、stdout

再コンパイルして実行

于 2012-10-08T10:24:58.533 に答える