Hi All,

I'm actually making a little program but I'm encountering an error that I can't manage to resolve.

So I have a linked list of "User" (each User has got a pointer to the previous User and another pointer to the next User). At First, the List is empty and initialized by the UserInit function. The 2 global User First and Last are pointing on each other as there is at this moment no real User.

At the line 73-77 : I allocate five new User
At the line 113-122 : I put a name in the 'surnom' variable and I add the User in the List.
At the line 97-105 : In the meantime, I made 10 threads that will each add 10 Users to the List.

The Problem : The function AfficheList is working great and shows all the Users lying in the List so the link between each User is correct (good pointer on good User).

When I want do delete (using the DeleteUser function) an User, there is no problem for the five Users allocated in the main (un,deux,trois,quatre,cinq "User") BUT if I want to delete any of the 100 Users allocated by the threads . . . it's ALWAYS getting me an error on the free of the concerned User . . . I verified that each adress lying in the next or previous part of the User is the good one and this is the case !

So I hope someone of you will try to help me !
Thank you !:icon_wink:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <string.h>
#include <pthread.h>
#include <signal.h>
#include "semadd.h"

#define MAXCHAR 25

struct User
{
	struct User *prev;
	char surnom[MAXCHAR];
	char motdepasse[MAXCHAR];
	int handle;
	char nomsalon[MAXCHAR];
	struct User *next;	
};

void UserInit(void);
int AddUser(struct User *);
struct User* SearchUser(char *);
int DeleteUser(char *);
void AfficheListe(void);
void* fctThread(struct User *);
void* SynchroThread(void*);
void traitement_signal(int);

pthread_t MonThread[10];
pthread_t Synchronisation;

int Sem1;
int Sem2;
struct sigaction sigAct;
struct User First;
struct User Last;

void traitement_signal(int signum)

{
	int i = 0;
	printf("SIGINT recu !\n");
	struct User *Temp;	
	struct User *Old;	
	struct User *ToDelete;
		
	while(First.next != &Last)
	{	
		printf("yop ! ! ! \n");
		DeleteUser("");
	}
	
	/*printf("yop ! \n");
		Old = Last.prev;	
		Temp = Temp->prev;
		free(Old);
		Last.prev = Temp;*/

}

int main (void)
{
	int i=0; 
	int a=0;
	int errno = 0;
	int *test; 
	struct User *PUser;
	struct User *un,*deux,*trois,*quatre,*cinq;
	
	un = malloc(sizeof(struct User));
	deux = malloc(sizeof(struct User));
	trois = malloc(sizeof(struct User));
	quatre = malloc(sizeof(struct User));
	cinq = malloc(sizeof(struct User));
	
	sigemptyset(&sigAct.sa_mask);

	sigAct.sa_handler=traitement_signal;

	sigaction(SIGINT,&sigAct,NULL);

	
	Sem1 = sem_transf(12345);
	Sem2 = sem_transf(67890);
	
	UserInit();	
	
	errno = pthread_create(&Synchronisation, NULL,(void *(*)(void *))SynchroThread,(void*)i);
    if (errno)
    {
       	printf("ERREUR; code de retour pthread_create() est %d\n", errno);
    }	

	for(i=0; i<10 ; i++)
	{
		PUser = malloc(10 * sizeof(struct User));
	
		errno = pthread_create(&MonThread[i], NULL,(void *(*)(void *))fctThread,PUser);
      	if (errno)
      	{
         	printf("ERREUR; code de retour pthread_create() est %d\n", errno);
      	}	
  	}
  	
  	for(i=0; i<10 ; i++)
	{
  		pthread_join(MonThread[i],(void **)&errno);
  	}	
	
	strcpy(un->surnom ,"un");
	AddUser(un);
	strcpy(deux->surnom ,"deux");
	AddUser(deux);
	strcpy(trois->surnom ,"trois");
	AddUser(trois);
	strcpy(quatre->surnom ,"quatre");
	AddUser(quatre);
	strcpy(cinq->surnom ,"cinq");
	AddUser(cinq);

	AfficheListe();
  	DeleteUser(un->surnom); 	
  	DeleteUser(quatre->surnom);
  	DeleteUser(cinq->surnom);
  	printf("ici ?\n\n");
  	un = PUser->next;
 	DeleteUser(PUser->surnom);
  	printf("ici ?\n\n");
 	DeleteUser(un->surnom);
 	  	printf("ici ?\n\n");
	AfficheListe();  	

	getchar();
	
	return 0;
}

void UserInit(void)
{
	First.prev = NULL;
	First.next = &Last;	
	Last.prev = &First;
	Last.next = NULL;
}

int AddUser(struct User *UserRecu)
{
	int i=0;
		
	struct User *Temp;
	Temp = &First;
		
	while(Temp != NULL)
	{
		if(strcmp(Temp->surnom,UserRecu->surnom)==0)
		{
			i=1;
		}
		Temp = Temp->next;
	}
	
	Temp=&First;
	if(i==0)
	{
		UserRecu->prev = &First;
		UserRecu->next = Temp->next;
		First.next = UserRecu;
		Temp = Temp->next;
		Temp = Temp->next;
		Temp->prev = UserRecu;	
		
		return 1;	
	}
	else
	{
		printf("Erreur : Surnom deja en cours d'utilisation ! \n");
		return 0;
	}	
}

void AfficheListe(void)
{
	int i=1;
	struct User *Temp;
	Temp = First.next;
	
	printf("Liste d'User : \n");
	
	while(Temp->next != NULL)
	{		
		printf("           %d\n", Temp);
		printf("%d -> %d  %s  %d\n", i,Temp->prev,Temp->surnom,Temp->next);
		Temp = Temp->next;
		i++;
	}
}

struct User* SearchUser(char *surnom)
{		
	struct User *Temp;
	Temp = &First;
		
	while(Temp != NULL)
	{
		if(strcmp(Temp->surnom,surnom)==0)
		{
			return Temp;
		}
		Temp = Temp->next;
	}
	
	return NULL;
}

int DeleteUser(char *surnom)
{
	struct User *Temp;	
	struct User *Old;	
	struct User *ToDelete;
	
	Old = &First;
	Temp = First.next;	
	
	while(Temp->next != NULL)
	{		
		if(strcmp(Temp->surnom,surnom) == 0)
		{
			ToDelete = Temp;
			Old->next = Temp->next;
			Temp = Temp->next;
			Temp->prev = Old;									
			free(ToDelete);
			
			return 1;
		}		
		Old = Temp;
		Temp = Temp->next;		
	}

	printf("Erreur : L'utilisateur n'a pu etre trouve !\n");	
	
	return 0;
}

void* fctThread(struct User *PUser)
{	
	int i=0;
	int j=0;
	int okay=1;
	
	srand(time(NULL));
	
	for(i=0;i<10;i++)
	{	
		for(j=0;j<5;j++)
		{
			PUser->surnom[j] = rand() %26+'a'; 
		}	
		PUser->surnom[j] = '\0';
		PUser->handle = -1;
		printf("User = %s\n", PUser->surnom);
		p(Sem1);
			okay = AddUser(PUser);
		v(Sem2);
		if(okay==1)
			PUser++;
		else
			i--;
	}

	pthread_exit(NULL);

}

void* SynchroThread(void * a)
{
	while(1)
	{
		v(Sem1);
		p(Sem2);
	}
	
	pthread_exit(NULL);
}

fctThread() does add the names to the pointer in the thread's parameter, but your program just tosses that pointer into the bit bucket (throws it away). Line 99 allocates the pointer, line 100 creates the array and passes the pointer to it, then ---- nothing. The pointer is never saved anywhere, nor is it freed, causing a memory leek to boot.

I can only guess why AddUser() fails to add the structure to the global linked list -- you need to synchronize thread access to all globals so that two or more threads don't attempt to write to the same object at the same time. semaphonres are usually used for that purpose.

First of all thank you for your answer !

As you can see at line :

265 # p(Sem1);
266 # okay = AddUser(PUser);
267 # v(Sem2);

This is the protection using two semaphores, so there is no problem at this point.

Moreover, the AfficheListe() Function is able to read all the the Users present in the List (from First to Last) . . . So the pointers are pointing right on each User of the list . . . The thing I can't manage to understand is why I can't Free() those elements even if I have the good adress ! :icon_neutral:

Anyway thank you for your help ! :)

This article has been dead for over six months. Start a new discussion instead.