结构中联合内的结构在函数调用期间发生更改

时间:2012-10-07 04:45:14

标签: c multithreading function struct

我正在使用c实现信号量的多线程生产者 - 消费者计划。每个缓冲区结构都有两个通用信号量 - 一个用于空缓冲区,另一个用于完整缓冲区。但是,当程序进入readInput函数时,这两个信号量的值将更改为随机值。线程结构中的信号量很好,但是线程结构中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是什么。

1 个答案:

答案 0 :(得分:0)

信号量和缓冲区在主线程中创建为堆栈变量,因此当主线程退出指向信号量的地址时,缓冲区无效且行为不可预测。进行适当的设计并为变量提供适当的范围,暂时使所有变量成为全局变量。在上面的代码中将以下内容作为全局

  1. 信号量互斥; //用于互斥的二进制信号量。

  2. IO输入,buffer1,buffer2,buffer3,输出; // stdin,3个缓冲区,stdout

  3. 重新编译并执行