为什么我得到内存段故障时,我正在运行这个C程序

fcg9iug3  于 2022-12-17  发布在  其他
关注(0)|答案(2)|浏览(99)

我有两个线程,它们应该使用相同的内存。主方法应该启动两个线程。TråA必须读取文件的内容,并与TråB共享它。TråB也必须接收TråA共享的数据,并循环通过和计数文件中的字节数。两个线程都运行,但在程序终止前的最后一步I内存段故障。我使用信号量之间的线程通信。这里我的代码:

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>
#define BUFFER_SIZE 4096
typedef struct _Buffer
{
    int size;
    char data[BUFFER_SIZE];
} Buffer;

sem_t task1, task2;

void *thread_A(void *arg);
void *thread_B(void *arg);
int main(int argc, char *argv[])
{
    
    Buffer *memory = malloc(sizeof(Buffer));

    sem_init(&task1, 0, 0);
    sem_init(&task2, 0, 0);

    pthread_t thread_A_id;
    pthread_t thread_B_id;

    pthread_create(&thread_A_id, NULL, &thread_A,  &memory);

    pthread_create(&thread_B_id, NULL, &thread_B,  &memory);
    
    if (pthread_join(thread_A_id, NULL) != 0)
    {
        perror("Error joining thread A");
        exit(1);
    }

    if (pthread_join(thread_B_id, NULL) != 0)
    {
        perror("Error joining thread B");
        exit(1);
    }

    free(memory);
    return 0;
}

void *thread_A(void *arg)
{
    Buffer *buffer = (Buffer*) arg;

    FILE *pdf_file = fopen("file.pdf", "rb");
    if (pdf_file == NULL)
    {
        perror("Can not open the file");
    }

    printf("size of struct %ld\n", sizeof(Buffer));
    buffer->size = fread(&buffer->data, sizeof(char), BUFFER_SIZE, pdf_file);

    fclose(pdf_file);

    sem_post(&task1); 
   
    sem_wait(&task2);
    printf("A is out\n");
    return NULL;
}

void *thread_B(void *arg)
{
    printf("IAM IN TREAD B");
    Buffer *buffer = (Buffer*) arg;
    
    sem_wait(&task1);
    int i=0;;

    int byte_counts[256] = {0};
    while (buffer->size != i) {
                    
        unsigned char byte = buffer->data[i];
        byte_counts[byte]++;

        i++;
    }

    for (int i = 0; i < 256; i++)
    {
        printf("Byte-value %02X: %d\n", i, byte_counts[i]);
    }

    sem_post(&task2);

    printf("threadB is done 2\n");
    return NULL;
}
3mpgtkmj

3mpgtkmj1#

memory是指向BufferBuffer *)的指针,通过获取它的地址,可以获得指向缓冲区(Buffer **)的指针:

Buffer *memory = malloc(sizeof(Buffer));
    ...
    pthread_create(&thread_A_id, NULL, &thread_A,  &memory);
    pthread_create(&thread_B_id, NULL, &thread_B,  &memory);

但在线程函数中,您假设argBuffer *

Buffer *buffer = (Buffer*) arg;

这会导致未定义的行为。
很明显,有一个间接太多; memory已经是一个指针,所以我们不需要获取它的地址:

pthread_create(&thread_A_id, NULL, &thread_A,  memory);
    pthread_create(&thread_B_id, NULL, &thread_B,  memory);
ve7v8dk2

ve7v8dk22#

如果文件无法打开,fread将返回-1,并且不检查它,因此thread_B中的循环将首先从buffer-〉data读取垃圾,然后继续超出限制(因为与-1比较)。
因此,首先,fopen()缺少错误处理- thread_a在perror之后继续,其次-fread()之后缺少错误检查。
顺便说一下,在之后检查if(buffer-〉size == i)**while(buffer-〉size!= i)**是多余的:)

相关问题