简体   繁体   中英

invalid write of size 8 when using sem_t

initially when I have only one sem_t *queue inside the struct, when I initialize it, the programs run without any errors and problems.

 #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);

 }

however, when I have two sem_t in struct barrier when I initialize and run with Valgrind, it signals to me that there is an invalid write of size 8, even though the program runs and outputs normally.

#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);   
}

The main function was a template given which should not have any issues. Valgrind has no issue with memory leaks as well only errors indicating invalid write and read of size 8. so here's the main function:

#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;
  }

THis is part of the Valgrind errors:

Invalid write of size 8 at 0x1098BB: barrier_init (in /home/hzxin/work/2106/lab3/L3/ex1/ex1) by 0x10948F: main (in /home/hzxin/work/2106/lab3/L3/ex1/ex1) Address 0x4a730b0 is 0 bytes after a block of size 16 alloc'dat 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)

I added a small main function and also a simple deinit function. Compiling with gcc 9.3.0 and checking with valgrind 3.15 yields no problem. Double check how you are calling your functions.

Running your updated code in Valgrind works just fine for me.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM