2011-12-18 127 views
2

我在做一個練習。目標是讓C程序破解DES加密密碼。 現在我有以下執行流程:pthread總線錯誤

  1. 加載字典。
  2. 字典搜索。
  3. 蠻力搜索前4個字符。
  4. 字典搜索結合蠻力(搜索 組合)。只有7-6個字符的字典單詞。
  5. 蠻力搜索前5個字符。
  6. 字典搜索結合蠻力(搜索 組合)。只有5-4個字符的字典單詞。
  7. 蠻力搜索最多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; 
} 
+0

請將您的代碼粘貼到此處,而不是在其他某個網站上。 http://stackoverflow.com/是這裏成爲高質量問題和答案的存儲庫;當你的代碼主機關閉他們的大門或過期時,會發生什麼?這將變得(更)無用,對未來的其他人沒有任何幫助。謝謝! – sarnold 2011-12-18 11:01:20

+0

好多了,謝謝@Cody。 – sarnold 2011-12-18 11:07:02

+0

對不起,在pastebin上發佈代碼,但我是新來的stackoverflow和格式化代碼有困難... – user903673 2011-12-18 11:12:44

回答

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]),但我認爲這不太清晰。)

我總是有點擔心,當我用演員沉默警告時,正如我在這裏所做的那樣,但是這確實執行了一次大的分配,而不是數千個微小的分配,這可能會導致巨大的性能差異。 (測試並參見。)

+0

我知道如何分配int的2d數組,但是我遇到了字符問題。我試圖這樣做,但它仍然失敗:char * words [ctr]; \t int i; (i = 0; i user903673 2011-12-18 12:53:18

+0

謝謝。它和它的工作:) char **的話; \t words = malloc(ctr * sizeof(char *)); \t int i; \t \t //循環計數器變量 \t for(i = 0; i user903673 2011-12-18 15:36:57