ошибка шины pthread - PullRequest
       6

ошибка шины pthread

2 голосов
/ 18 декабря 2011

Я делаю упражнение. Цель состоит в том, чтобы сделать программу на C, чтобы взломать DES зашифрованный пароль. Прямо сейчас у меня есть следующий поток выполнения:

  1. Загрузить словарь.
  2. Поиск по словарю.
  3. Поиск грубой силы первых 4 символов.
  4. Поиск по словарю в сочетании с грубой силой (поиск комбинаций). Только словарные слова из 7-6 символов.
  5. Поиск грубой силы первых 5 символов.
  6. Поиск по словарю в сочетании с грубой силой (поиск комбинаций). Только словарные слова из 5-4 символов.
  7. Поиск грубой силы до 8 символов.

Программа работает нормально, но я хочу улучшить ее, используя несколько потоки: 1-й поток - основной 2-й поток - словарь и словарь в сочетании с грубой силой поиск 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 Ответ

2 голосов
/ 18 декабря 2011

Я собираюсь догадаться , что это ваша проблема:

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]), но я не думаю, что это так же разборчиво.)

Меня всегда немного беспокоит, когда я приглушаю предупреждение с использованием приведения, как я это делал здесь, но при этом выполняется одно большое распределение вместо тысяч маленьких крошечных, что может привести к огромной разнице в производительности. (Проверьте оба и посмотрите.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...