pthread总线错误

时间:2011-12-18 10:59:38

标签: c pthreads

我正在做运动。目标是在C中制作一个程序来破解DES加密密码。 现在我有以下执行流程:

  1. 加载字典。
  2. 字典搜索。
  3. 强力搜索前4个字符。
  4. 字典搜索结合蛮力(搜索 组合)。只有7-6个字符的字典单词。
  5. 强行搜索前5个字符。
  6. 字典搜索结合蛮力(搜索 组合)。只有5-4个字符的字典。
  7. 强力搜索最多8个字符。
  8. 该程序运行正常,但我想通过使用多个来改进它 主题: 第一个主题 - 主要 第二个线程 - 字典和字典结合蛮力 搜索 第3个帖子 - 强力搜索

    我开始制作一个基本的字典搜索线程函数,但是 它失败了,总线错误(Mac OS X)应该开始读取单词 来自字典文件。相同的代码在常规非常有效 线程功能......

    以下是代码:

    #include <pthread.h>
    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    
    #define _XOPEN_SOURCE
    #define MAXLINE 40
    #define MAXPASS 9
    
    /* dictionary search thread function */
    void * dictionary(void * argv)
    {
        /* initializing SALT */
        char salt[3];               // defining salt (length is always 2 chars + "\0")
        strncpy(salt, argv, 2);     // copying the first 2 characters from encrypted password to salt
        salt[2] = '\0';             // placing null character to make salt a string
    
        /* defining and initializing password */
        char password[14];
        strcpy(password, argv);
        /* defining candidate */
        char  candidate[MAXPASS];
    
        /* opening file */
        FILE *fp;
        if ((fp = fopen("/usr/share/dict/words", "r")) == NULL)
        {
            printf("Error: Can not open file.\n");
            return (void *) -1;
        }
        printf("Open file: Ok\n");
        char line[MAXLINE];
        printf("Counting words: "); 
        /* counting words the file contains */
        int ctr = 0;    // words counter variable 
        int len;        // store length of the current line
        while (fgets(line, MAXLINE, fp) != NULL && line[0] != '\n')
        {
            if ((len = strlen(line)) <= MAXPASS && len >= 4)
                ctr++;  // will be real+1 when the loop ends
        }
        ctr--;          // adjusting to real words count
        rewind(fp);     // go back to the beginning of file
        printf("%d words\n", ctr);
    
        /* create an array of strings and fill it with the words from the dictionary */
        printf("Creating array for file contents: ");
        char words[ctr][MAXPASS];
        int i = 0;      // loop counter variable
        printf("Ok\n");
        /************************************* BUS ERROR *********************************************/
        printf("Reading file contents: ");
        while (fgets(line, MAXLINE, fp) != NULL && line[0] != '\n')
        {
            if ((len = strlen(line)) <= MAXPASS && len >= 4)
            {
                line[len-1] = '\0';
                strcpy(words[i], line);
                printf("%d: %s\n", i, words[i]);
                i++;
            }
        }
        printf("Ok\n");
        printf("Loaded %d words...\n", ctr);
    
        /* closing file */
        printf("Close file: ");
        if (fclose(fp) != 0)
        {
            fprintf(stderr, "Error: Can not close file\n");
            return (void *) -2;
        }
        printf("Ok\n");
    
        /* starting search dictionary search */
        printf("Starting Dictionary Search...\n");
        int match = 0;
        char * encrypted;
        int n;
        for (i = 0; i <= ctr && !match; i++)
        {
            encrypted = crypt(words[i], salt);
            if ((strcmp(encrypted, password)) == 0)             // if candidate == password
            {
                match = 1;
                strcpy(candidate, words[i]);
                printf("Password: %s\n", candidate);
                return (void *) 1;
            }
        }
    
        return (void *) 0;
    }
    int main(int argc, char * argv[])
    {
        /* if there are less/more than 1 argument, notify the user and exit with an error code  1 */
        if (argc != 2)      // first argument is always the name of the program
        {
            printf("Error 1: Wrong number of arguments\n");             
            return 1;
        }
        /* if the length of the argument is less/more than 13 characters, notify the user and exit with an error code 2 */
        int length = strlen(argv[1]);
        if (length != 13)
        {
            printf("Error 2: The length of an encrypted password should be 13 characters\n");
            return 2;
        }
    
        pthread_t dct;      // dictionary thread identifier
        void *status;       // thread return value
    
        /* creating dictionary thread */
        pthread_create(&dct,NULL,dictionary,argv[1]);
    
        printf("Waiting for thread to terminate...\n");
        pthread_join(dct,&status);
    
        //printf("Return Value: %d\n",(int)status);
    
        return 0;
    }
    

1 个答案:

答案 0 :(得分:2)

我要这是你的问题:

char words[ctr][MAXPASS];

当你运行一个单线程程序时,你有足够的地址空间让堆栈增长,库和程序可执行空间长大,堆积在中间。

但是当你运行多线程程序时,每个线程都有自己的堆栈,如果线程可用的堆栈空间明显小于字典大小,我也不会感到惊讶。 (有关每线程堆栈大小默认值的详细信息,请参阅系统上的pthread_attr_getstack()联机帮助页。)

使用malloc(3)分配该数组,看看你的程序是否进一步发展。

char *words;
words = malloc(ctr * sizeof(char));
int i; // loop counter variable
for (i = ; i < ctr; i++)
    words[i] = malloc(MAXPASS * sizeof(char));

如果您发现多个malloc(3)调用引入了足够的内存碎片,您可以使用一些略微粗略的转换来分配单个大块内存并将其视为与多维数组完全相同:

$ cat multidimensional.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define NWORDS 1000
#define WORDLEN 10

void fun(char words[NWORDS][WORDLEN]) {
    int i, j;
    for (i=0; i<NWORDS; i++) {
        strcpy(words[i], "test");
    }

    for (i=0; i<NWORDS; i++) {
        printf("%s\n", words[i]);
    }
    return;
}


int main(int argc, char* argv[]) {
    char *w = malloc(NWORDS * WORDLEN * sizeof(char));
    memset(w, 0, NWORDS * WORDLEN * sizeof(char));
    fun((char (*)[WORDLEN]) w);

    return 0;
}

你必须使用另一个函数,因为你不能分配给一个数组但是当你编写一个应该传递一个数组作为参数的函数时,它实际上会衰减到函数中的指针。致电:char (*)[WORDLEN]。 (它本来可以写成:void fun(char (*)[WORDLEN])但我不认为这是清晰的。)

当我在演员阵容中沉默警告时,我总是有点担心,就像我在这里所做的那样,但这确实执行了一次大的分配,而不是成千上万的微小分配,这可能会产生巨大的性能差异。 (测试两者并查看。)