0

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

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

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

4

3 回答 3

3

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

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

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

于 2012-05-22T11:30:39.643 回答
2

您传递&argv[1]a_to_temp()函数,它是 a char **,然后尝试使用它,就好像它是 a 一样char *&argv[2]temp_to_b()函数同上。这不是幸福的秘诀;核心转储是一个相当合理的响应。

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

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


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

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

于 2012-05-22T11:34:37.893 回答
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 的问题:我是否被迫使用 pthread_cond_broadcast (over pthread_cond_signal) 以保证 *my* 线程被唤醒?

于 2012-06-12T20:33:20.733 回答