【问题标题】:invalid write of size 8 when using sem_t使用 sem_t 时大小为 8 的无效写入
【发布时间】: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 库

标签: c valgrind


【解决方案1】:

我添加了一个小的 main 函数和一个简单的 deinit 函数。 使用 gcc 9.3.0 编译并使用 valgrind 3.15 进行检查没有问题。 仔细检查你是如何调用你的函数的。

在 Valgrind 中运行更新后的代码对我来说效果很好。

【讨论】:

  • 请不要在答案中包含完整的源代码,因为这会使评估答案变得困难。通常最好只包含相关行并在必要时解释解决方案。
  • 我已经更新了主函数,它是一个模板,我不知道如何简化。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-02-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-16
  • 1970-01-01
  • 2021-12-24
相关资源
最近更新 更多