为什么这个多线程C程序给我分段错误?

时间:2012-05-22 11:23:47

标签: c multithreading segmentation-fault

我的目的是使用多线程转置两个文件。但是下面的程序给了我分段错误。

#include   <stdio.h>
#include  <stdlib.h>
#include <pthread.h>
#include  <string.h>


void *a_to_temp( void *filea);
void copyFile( FILE *in, FILE *out );
void *temp_to_b( void *fileb);
void *b_to_a(void *ab);

struct files{
    char a[80];
    char b[80];
} ab;

pthread_mutex_t temptob     = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t btoa        = PTHREAD_MUTEX_INITIALIZER;

main(int argc, char **argv)
{
    fprintf(stderr, "in main");

    pthread_t thread1, thread2, thread3;
    strcpy( ab.a, argv[1]);
    strcpy(ab.b, argv[2]);

    int  iret1, iret2, iret3;

    pthread_mutex_lock( &temptob );
    pthread_mutex_lock( &btoa );

    iret1 = pthread_create( &thread1, NULL, a_to_temp, (void*) &argv[1]);

    iret2 = pthread_create( &thread2, NULL, b_to_a, (void*) &ab);

    iret3 = pthread_create( &thread3, NULL, temp_to_b, (void*) &argv[2]);


    pthread_join( thread1, NULL);
    pthread_join( thread2, NULL);
    pthread_join( thread3, NULL);

    exit(0);
}


void *a_to_temp( void *filea) {
    FILE *a = fopen((char *)filea, "r");    
    FILE *f = fopen( "temp", "w");
    copyFile( a , f);
    fclose(f);
    fclose( a); 
    pthread_mutex_unlock( &temptob );
}

void *temp_to_b( void *fileb) {
    pthread_mutex_lock( &temptob );
    FILE *b = fopen((char *)fileb, "r");
    FILE *f = fopen( "temp", "r");
    copyFile( f, b);
    fclose(f);  
    pthread_mutex_unlock( &btoa );
}

void *b_to_a(void *ab) {
    pthread_mutex_lock( &btoa );
    FILE *a = fopen(((struct files *) ab)->a, "w"); //
    FILE *b = fopen(((struct files *) ab)->b, "r");//
    fprintf(stderr, "c files opened");
    copyFile( b, a);
    fclose(a);
    fclose(b);
}

void copyFile( FILE *in, FILE *out) {
    char ch;
    while(!feof(in)) {
        ch = getc(in);  
        if(!feof(in)) putc(ch, out);            
    }
}

我通过打印值测试了代码,直到主函数结束。我猜这个错误应该在其中一个函数中。

3 个答案:

答案 0 :(得分:3)

您的代码的一个问题是您将互斥锁定在一个线程中并在另一个不允许的线程中解锁它。

如果您尝试在不拥有互斥锁的线程中解锁互斥锁,则可能导致未定义的行为。

例如,您的pthread_mutex_lock( &temptob );位于主线程中,而pthread_mutex_unlock( &temptob );位于a_to_temp中。

答案 1 :(得分:2)

您将&argv[1]传递给a_to_temp()函数char **,然后尝试使用它,就像它是char *一样。同样适用于&argv[2]temp_to_b()功能。这不是快乐的秘诀;核心转储是一个非常合理的反应。

最简单的解决方法是将&放入pthread_create()来电。另一种方法是处理被调用函数中的char **

注意:这只是修复了访问错误数据导致的核心转储。代码也可能存在算法问题,确保发生正确的同步。在这里使用线程是否有任何性能提升是有争议的。的确,可能没有。但这可能与练习的重点相关,即使线程代码完全正常工作。


  

你能告诉我如何序列化我的线程。我试图使用似乎没有帮助的互斥量。

一项是确保您对每次系统调用进行错误检查;目前,你假设一切都会奏效。但是,我认为Jay处于正确的轨道上,“锁定互斥锁的线程也必须将其解锁”。您可能需要一个或两个条件(pthread_cond_init()等)来控制对文件的访问而不是互斥锁。

答案 2 :(得分:1)

很抱歉干预,但我的印象是你真正想要实现的不一定是互斥,而是操作的序列化(即:订购操作:第一:copy_a_to_temp;第二:copy_b_to_a;第三个:copy_temp_to_b)。以上答案适用于通过同一个线程锁定和解锁互斥锁。但是,对于排序(或者更准确地说,强制线程等待直到另一个完成任务)并不是真正的互斥体工作,而是监视器/条件变量的工作(或者,一种更复杂的信号量方式,因为信号量可以实现监视器)。要强制一个线程(例如,copy_b_to_a必须在copy_a_to_temp完成其工作之前发生),您应该使用pthread_cond_wait。有关如何使用pthread_cond_wait的问题,请参阅此问题:Am I forced to use pthread_cond_broadcast (over pthread_cond_signal) in order to guarantee that *my* thread is woken up?