为什么我的C程序总是出现分段错误

为什么我的C程序总是出现分段错误,c,C,我一直在尝试在C上实现线程同步。但是,当我调用我希望线程执行的函数时,我总是遇到分段错误。那么,有人可以就这个问题提出解决方案吗 这是我的密码 #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <semaphore.h> #include <fcntl.h> #include <unistd.h> #include <sys/sta

我一直在尝试在C上实现线程同步。但是,当我调用我希望线程执行的函数时,我总是遇到分段错误。那么,有人可以就这个问题提出解决方案吗

这是我的密码

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

我在评论中解释了主要问题:


您没有向线程函数传递有效指针。在
printf();在调用
Learning()
解除对无效非指针的引用时,您显然无法逃脱它的惩罚

解决方案是在主程序中创建一个整数数组,该数组保存机器人ID号(
int-ID[N];
)。然后,初始化每个元素并将
&id[i]
传递到
pthread\u create()

您不应使用
%d
格式打印地址(即使它适用于32位系统;但不适用于64位系统)。正确的方法是使用
%p
格式化地址。或者,在这种情况下,使用
*robot\u id
打印整数而不是地址

下面的代码对原始代码的修改最小,并且尚未编译或测试(可能在更改的行之外有问题):

#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义n5
#定义m3
#定义左侧(机器人id-1)%N
#定义右侧(机器人id+1)%N
pthread_t robots_id[N];
sem_t模拟[M];
pthread_mutex_t server_mutex;
无效学习(int robot_id)
{
printf(“学习机器人=%d\n”,机器人id);
}
void*robotAct(void*id)
{
int*robot_id=id;
printf(“机器人id=%d\n”,*机器人id);//已更改
学习(*机器人id);
返回0;//已添加
}
int main(int argc,char*argv[])
{
int E,T;
int id[N];//已添加
E=atoi(argv[1]);
T=atoi(argv[2]);
printf(“初始化机器人!\n”);
//初始化模拟
for(int i=0;i
避免使用
pthread\u cancel()
结束线程;线程应该在控制下终止。例如,在主线程中可能设置了一个标志,指示线程应该停止,并且它们会定期检查。通常,
pthread\u join()
用于清理已完成的线程


对于以后的文章,请阅读如何创建MCVE()。显示的部分代码与问题无关-例如,互斥和信号量没有真正使用。

请注意,
(void*)i+1
在标准C中是非法的。您没有向线程函数传递有效指针。在
printf();在调用
Learning()
解除对无效非指针的引用时,您显然无法逃脱它的惩罚。
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
#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;
}