繁体   English   中英

为什么这个多线程程序会出现段错误?

[英]Why this mutil-threaded program is Segfaulting?

我正在研究使用互斥体解决哲学家用餐问题的解决方案,但是该程序可能因与线程相关的错误而出现段错误
我在这里要做的基本上是将 fork 视为互斥锁并创建一个 function void *eat(void *arg) ,然后关闭关键部分(关键部分只是声明其 id 的线程,它的当前正在吃)无论 function 被调用什么,然后我遍历我所有的哲学家并检查它的 id(id 从 0 开始)是否可以被 2 整除。
第一轮只有线程 id 可以被 2 整除,第二轮只有线程 id 不能被 eat 整除,在无限循环中依此类推。
我知道这是一个非常简单的解决方案,可能一开始就无法解决问题。 所以请多多包涵。 如果您有任何问题,请在评论中告诉我。

struct typedef t_philo
{
    pthread_t thread;
    pthread_mutex_t fork;
    int id;
}
t_philo;

void *eat(void *arg)
{
    t_philo *philo = (t_philo *)arg;

    pthread_mutex_lock(&philo->fork);
    printf("philo with id: %i is eating\n", philo->id);
    pthread_mutex_unlock(&philo->fork);
    return (NULL);
}

void first_round(t_philo *philo, int len)
{
    for (int i = 0; i < len; i++)
        if (!(i % 2))
            pthread_join(philo[i].thread, NULL);
}

void second_round(t_philo *philo, int len)
{
    for (int i = 0; i < len; i++)
        if ((i % 2))
            pthread_join(philo[i].thread, NULL);
}


int main(int argc, char **argv)
{
    t_philo *philo;
    // how many philosophers is given as first arg.
    int len = atoi(argv[1]);
    if (argc < 2)
        exit(EXIT_FAILURE);
    philo = malloc(sizeof(*philo) * atoi(argv[1]));
    //this function add id's and initialize some data.
    init_data(philo, argv);
    for (int i = 0; i < len; i++)
        pthread_create(&philo[i].thread, NULL, eat(&philo[i]), &philo[i]);

        while (1)
        {
            first_round(philo, len);
            second_round(philo, len);
        }
    return 0;
}

OUTPUT

philo with id: 0 is eating
philo with id: 1 is eating
philo with id: 2 is eating
philo with id: 3 is eating
philo with id: 4 is eating
            .
            .
            .
            .
philo with id random is eating
[1]    29903 segmentation fault

Output 每次都达到一个随机 ID 和段错误,这就是为什么我断定它可能是一个线程错误。

pthread_create具有以下原型:

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                   void *(*start_routine) (void *), void *arg);

start_routine是一个function 指针 但是,您使用错误的 arguments调用pthread_createeat(&philo[i]) 因此,程序正确调用了eat ,然后尝试调用NULL (从新线程),因为这是eat返回的值。 随机性来自实际创建线程的可变时间。

请注意,使用调试器应该可以帮助您轻松找到并修复问题。 像 gdb 这样的调试器有点难学,但一旦学会了,像段错误这样的错误就变得很容易修复了。 我也很惊讶像 clang 这样的编译器不会在编译时注意到输入问题。

main中, int len = argv[1]; 是错的。 如果您在启用警告的情况下进行编译(例如-Wall ),则此语句将被编译器标记。

照原样,您将获得len巨大价值。 因此,稍后, for循环将溢出您分配的数组并且您有 UB。

你可能想要: int len = atoi(argv[1]); 正如您对malloc的那样。

而且,您想在argc检查之后执行此操作。

而且,为什么要 [使用修复程序] 调用atoi两次?

这是重构的代码:

int
main(int argc, char **argv)
{
    t_philo *philo;

    if (argc < 2)
        exit(EXIT_FAILURE);

    // how many philosophers is given as first arg.
    int len = atoi(argv[1]);

    philo = malloc(sizeof(*philo) * len);

    // do stuff ...

    return 0;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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