简体   繁体   中英

Why do I keep getting segmentation fault in my C program

I've been trying to implement thread synchronization on C. However, I keep getting the segmentation fault when my invoke the function that I want the thread to execute. So anyone can suggest the solution on for this problem?

Here is my code

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>

#define N 5
#define M 3
#define LEFT (robot_id - 1) % N
#define RIGHT (robot_id + 1) % N

pthread_t robots_id[N];
sem_t simulations[M];
pthread_mutex_t sever_mutex;

void Learning(int robot_id)
{
    printf("learning robot = %d\n", robot_id);
}

void *robotAct(void *id)
{
    int *robot_id = id;
    printf("robot id = %d\n", robot_id);
    Learning(*robot_id);
}

int main(int argc, char *argv[])
{
    int E, T;

    E = atoi(argv[1]);
    T = atoi(argv[2]);

    printf("Initializing Robot!\n");

    //Initializes the simulations
    for (int i = 0; i < M; i++)
    {
        sem_init(&simulations[i], 0, 0);
    }

    //Initializes the robots
    for (int i = 0; i < N; i++)
    {
        printf("Robot %d is created\n", i + 1);
        pthread_create(&robots_id[i], NULL, robotAct, (void *)i + 1);
    }

    sleep(T);

    printf("Terminating Robots\n");
    for (int i = 0; i < N; i++)
    {
        pthread_cancel(robots_id[i]);
    }
    printf("Termination is completed!\n");
    printf("-------Report-------------\n");
    //getReport();
    return 0;
}

Here is my result that I keep getting

Initializing Robot!
Robot 1 is created
Robot 2 is created
Robot 3 is created
robot id = 1
robot id = 2
Robot 4 is created
robot id = 3
[1]    54477 segmentation fault  ./project 5 10

The main issue is explained in my comment:

You're not passing a valid pointer to the thread function. You sort of, mostly, almost get away with the misuse of it in the printf() call in robotAct() ; you emphatically do not get away with it in the call to Learning() where you dereference the invalid non-pointer.

A solution is to create an array of integers in the main program which holds robot ID numbers ( int id[N]; ). Then, initialize each element and pass &id[i] to pthread_create() .

You should not print addresses with the %d format (even though it works on 32-bit systems; it does not work on 64-bit systems). The correct technique is to use %p to format the address. Or, in this case, print the integer and not the address using *robot_id .

The code that follows has minimal adaptations to the original code and has not been compiled or tested (there could be problems outside the lines changed):

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>

#define N 5
#define M 3
#define LEFT (robot_id - 1) % N
#define RIGHT (robot_id + 1) % N

pthread_t robots_id[N];
sem_t simulations[M];
pthread_mutex_t sever_mutex;

void Learning(int robot_id)
{
    printf("learning robot = %d\n", robot_id);
}

void *robotAct(void *id)
{
    int *robot_id = id;
    printf("robot id = %d\n", *robot_id);        // Changed
    Learning(*robot_id);
    return 0;                                    // Added
}

int main(int argc, char *argv[])
{
    int E, T;
    int id[N];                                   // Added

    E = atoi(argv[1]);
    T = atoi(argv[2]);

    printf("Initializing Robot!\n");

    //Initializes the simulations
    for (int i = 0; i < M; i++)
    {
        sem_init(&simulations[i], 0, 0);
    }

    //Initializes the robots
    for (int i = 0; i < N; i++)
    {
        printf("Robot %d is created\n", i + 1);
        id[i] = i + 1;                                          // Added
        pthread_create(&robots_id[i], NULL, robotAct, &id[i]);  // Changed
    }

    sleep(T);

    printf("Terminating Robots\n");
    for (int i = 0; i < N; i++)
    {
        pthread_cancel(robots_id[i]);
    }
    printf("Termination is completed!\n");
    printf("-------Report-------------\n");
    //getReport();
    return 0;
}

Avoid using pthread_cancel() for ending the threads; the threads should terminate under control. For example, there might be a flag that you set in the main thread to indicate that the threads should cease, and they'd check that periodically. Normally, pthread_join() is used to clean up the completed threads.

For future posts, please read about how to create an MCVE ( Minimal, Complete, Verifiable Example ). There are parts of the code shown that are not relevant to the problem — the mutex and the semaphores, for example, are not really used.

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