【发布时间】:2021-06-07 04:08:45
【问题描述】:
最初,当我在结构中只有一个 sem_t *queue 时,当我初始化它时,程序运行时没有任何错误和问题。
#include <semaphore.h>
typedef struct barrier {
int count;
sem_t *queue;
} barrier_t;
void barrier_init ( barrier_t *barrier, int count );
#include "barrier.h"
#include <stdlib.h>
// Initialise barrier here
void barrier_init ( barrier_t *barrier, int count )
{
barrier->count = count;
barrier->queue = malloc(sizeof(sem_t));
sem_init(barrier->queue, 0, 0);
}
但是,当我初始化并使用 Valgrind 运行时,当我在结构屏障中有两个 sem_t 时,它向我发出信号,表明存在大小为 8 的无效写入,即使程序正常运行和输出。
#include "barrier.h"
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
typedef struct barrier {
int count;
sem_t *queue, *mutex;
} barrier_t;
void barrier_init ( barrier_t *barrier, int count )
{
barrier->count = count;
barrier->queue = malloc(sizeof(sem_t));
barrier->mutex = malloc(sizeof(sem_t));
sem_init(barrier->mutex, 0, 1);
sem_init(barrier->queue, 0, 0);
}
void barrier_wait ( barrier_t *barrier )
{
sem_wait(barrier->mutex);
barrier->count--;
sem_post(barrier->mutex);
if (barrier->count == 0) {
sem_post(barrier->queue);
}
sem_wait(barrier->queue);
sem_post(barrier->queue);
}
// Perform cleanup here if you need to
void barrier_destroy ( barrier_t *barrier )
{
sem_destroy(barrier->queue);
sem_destroy(barrier->mutex);
free(barrier->queue);
free(barrier->mutex);
}
主要功能是一个模板,应该没有任何问题。 Valgrind 没有内存泄漏问题,只有错误指示大小为 8 的无效写入和读取。所以这是主要功能:
#include <pthread.h>
#include <semaphore.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include "barrier.h"
sem_t *common_sem;
int waiting_at_barrier = 0;
typedef struct thread_task {
int thread_id;
barrier_t *barrier;
int thread_return;
int sleep_time;
} thread_task_t;
void* run_thread( void* task )
{
thread_task_t* thread_task = (thread_task_t*) task;
const int thread_id = thread_task->thread_id;
barrier_t *barrier = thread_task->barrier;
usleep( thread_task->sleep_time );
sem_wait( common_sem );
waiting_at_barrier++;
sem_post( common_sem );
printf ( "[Thread %2d] waiting on barrier\n", thread_id );
barrier_wait( barrier );
printf ( "[Thread %2d] exiting barrier\n", thread_id );
thread_task->thread_return = waiting_at_barrier;
pthread_exit(0);
}
int main ( int argc, char *argv[] )
{
if (argc < 2) {
printf("usage: %s threads [seed]\n", argv[0]);
exit(1);
}
if (argc > 2) {
srand(atoi(argv[2])); // [atoi] defaults to 0 if cannot be parsed.
}
const int total_threads = argc > 1 ? atoi(argv[1]) : 50;
// initialise common semaphore
common_sem = malloc(sizeof(sem_t));
sem_init( common_sem, 0, 1 );
barrier_t *barrier = malloc( sizeof(barrier_t) );
barrier_init( barrier, total_threads );
pthread_t threads[total_threads];
thread_task_t *thread_tasks = malloc(sizeof(thread_task_t) *
total_threads);
int i;
for (i = 0; i < total_threads; i++) {
thread_tasks[i].thread_id = i;
thread_tasks[i].barrier = barrier;
thread_tasks[i].sleep_time = (rand() % 500) * 1000;
pthread_create( &threads[i], NULL, run_thread, (void*)
&thread_tasks[i] );
}
// wait and collect the tasks
bool error_found = false;
for (i = 0; i < total_threads; i++) {
pthread_join( threads[i], NULL );
if (thread_tasks[i].thread_return < total_threads) {
error_found = true;
printf ( "[Thread %2d] exited with %d other tasks (expected:
%d)\n",i,thread_tasks[i].thread_return,
total_threads );
}
}
free(thread_tasks);
barrier_destroy(barrier);
free(barrier);
sem_destroy( common_sem );
free( common_sem );
if (error_found) {
printf ( "Incorrect executions found\n" );
exit(1);
}
return 0;
}
这是 Valgrind 错误的一部分:
0x1098BB 大小为 8 的无效写入:barrier_init(在 /home/hzxin/work/2106/lab3/L3/ex1/ex1 中)由 0x10948F: 主要(在/home/hzxin/work/2106/lab3/L3/ex1/ex1) 地址 0x4a730b0 是大小为 16 的块后的 0 个字节 alloc'dat 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
【问题讨论】:
-
请显示
main。请添加相关#includes。请创建一个完整的minimal reproducible example。问题可能是barrier是无效指针。 -
@KamilCuk 更新了 Main
-
你的编译和 valgrind 调用是什么?
-
@Eben 模板中有一个Makefile,Makefile的内容如下:
CC=gcc CFLAGS=-Wall LDLIBS=-lpthread .PHONY: clean ex1: barrier.o ex1.o barrier.o: barrier.c barrier.h clean: rm barrier.o ex1.o ex1 .PHONY: all all: ex1 -
是的,Makefile 只是编译它并链接到 pthread 库