Problem z wskaźnikami (zwalnianie pamięci po alokacji). Przypisywana ta sama wartość

0

Mam mały problem w projekcie na studia. Dawno nie kodowałem nic w C i troszkę zagmatwałem się ze wskaźnikami i alokacją. Będę wdzięczny za pomoc.

W poniższej funkcji mam dwa problemy:

  • nie mogę zwrócić pamięci zaalokowanej przez *h,
  • wszystkie elementy tablicy: rainbowtab[0..n][1] mają taką samą wartość, równą wartości zwróconej w ostatniej iteracji funkcji hash(r)
/*
 * Funkcja zwracająca dwuwymiarową tablicę tęczową, o danej głębokości i rozmiarze. Jako
 * argument otrzymuje również listę wyrazów, z których będą generowane ciągi.
 */
char*** createRainbowTable(char **wordstab, int deep, int n) {
    int i;
    int j;

    char *h = (char *) malloc(DES_CHARS_NUM * sizeof (char));
    if (h == NULL) {
        fprintf(stderr, "Nie mozna przydzielic pamieci 03");
        return NULL;
    }
    char *r = (char *) malloc(RED_CHARS_NUM * sizeof (char));
    if (r == NULL) {
        fprintf(stderr, "Nie mozna przydzielic pamieci 04");
        return NULL;
    }
    /*Alokacja pamięci dla tablicy*/
    char ***rainbowtab = (char ***) malloc(n * sizeof (char **));
    for (i = 0; i < n; i++) {
        *(rainbowtab + i) = (char **) malloc(deep * sizeof (char *));
        for (j = 0; j < deep; j++)
            *(*(rainbowtab + i) + j) = (char *) malloc(DES_CHARS_NUM * sizeof (char));
    }

    if (rainbowtab == NULL) {
        fprintf(stderr, "Nie mozna przydzielic pamieci 05");
        return NULL;
    }

    for (j = 0; j < n; j++) {
        for (i = 0; i < deep; i++) {

            if (i == 0) {
                h = (char *) hash(*(wordstab + j));
                printf("rainbow[%d][%d]=%s\n", j, i, h);
            }

            if (i > 0 && i % 2 == 0) {
                h = (char *) hash(r);
                printf("rainbow[%d][%d]=%s\n", j, i, h);
            }

            if (i % 2 != 0) {
                r = (char *) reduce(h);
                printf("rainbow[%d][%d]=%s\n", j, i, r);
            }

            if (i == deep - 1) {
                rainbowtab[j][1] = hash(r);
            }
        }

        rainbowtab[j][0] = *(wordstab + j);
    }

    //free(h);
    free(r);

    return rainbowtab;
}
0

po pierwsze w tym warunku

    char *r = (char *) malloc(RED_CHARS_NUM * sizeof (char));
    if (r == NULL) {
        fprintf(stderr, "Nie mozna przydzielic pamieci 04");
        return NULL;
    }

musisz zwolnić pamięć już zaalokowanego "h", podobnie jak w tym

    if (rainbowtab == NULL) {
        fprintf(stderr, "Nie mozna przydzielic pamieci 05");
        return NULL;
    }

"h" i "r"
Pokaż co pluje kompilator jak wywołujesz funkcję free(h)

0

Tu jest output kompilatora, po odkomentowaniu free(h).

./rainbowtab

  • glibc detected *** ./rainbowtab: double free or corruption (out): 0x40065140 ***
    ======= Backtrace: =========
    /lib/i386-linux-gnu/libc.so.6(+0x6b961)[0x400d1961]
    /lib/i386-linux-gnu/libc.so.6(+0x6d28b)[0x400d328b]
    /lib/i386-linux-gnu/libc.so.6(cfree+0x6d)[0x400d641d]
    ./rainbowtab[0x8048c8e]
    ./rainbowtab[0x80487b3]
    /lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xe7)[0x4007ce37]
    ./rainbowtab[0x80485f1]
    ======= Memory map: ========
    08048000-08049000 r-xp 00000000 08:08 1974630 /home/mateusz/NetBeansProjects/RainbowTable/rainbowtab
    08049000-0804a000 r--p 00001000 08:08 1974630 /home/mateusz/NetBeansProjects/RainbowTable/rainbowtab
    0804a000-0804b000 rw-p 00002000 08:08 1974630 /home/mateusz/NetBeansProjects/RainbowTable/rainbowtab
    09ac8000-09ae9000 rw-p 00000000 00:00 0 [heap]
    40000000-4001c000 r-xp 00000000 08:05 420866 /lib/i386-linux-gnu/ld-2.13.so
    4001c000-4001d000 r--p 0001b000 08:05 420866 /lib/i386-linux-gnu/ld-2.13.so
    4001d000-4001e000 rw-p 0001c000 08:05 420866 /lib/i386-linux-gnu/ld-2.13.so
    4001e000-4001f000 r-xp 00000000 00:00 0 [vdso]
    4001f000-40022000 rw-p 00000000 00:00 0
    40035000-4003d000 r-xp 00000000 08:05 420858 /lib/i386-linux-gnu/libcrypt-2.13.so
    4003d000-4003e000 r--p 00007000 08:05 420858 /lib/i386-linux-gnu/libcrypt-2.13.so
    4003e000-4003f000 rw-p 00008000 08:05 420858 /lib/i386-linux-gnu/libcrypt-2.13.so
    4003f000-40066000 rw-p 00000000 00:00 0
    40066000-401c0000 r-xp 00000000 08:05 420847 /lib/i386-linux-gnu/libc-2.13.so
    401c0000-401c1000 ---p 0015a000 08:05 420847 /lib/i386-linux-gnu/libc-2.13.so
    401c1000-401c3000 r--p 0015a000 08:05 420847 /lib/i386-linux-gnu/libc-2.13.so
    401c3000-401c4000 rw-p 0015c000 08:05 420847 /lib/i386-linux-gnu/libc-2.13.so
    401c4000-401c9000 rw-p 00000000 00:00 0
    401dd000-401f7000 r-xp 00000000 08:05 420953 /lib/i386-linux-gnu/libgcc_s.so.1
    401f7000-401f8000 r--p 00019000 08:05 420953 /lib/i386-linux-gnu/libgcc_s.so.1
    401f8000-401f9000 rw-p 0001a000 08:05 420953 /lib/i386-linux-gnu/libgcc_s.so.1
    40200000-40221000 rw-p 00000000 00:00 0
    40221000-40300000 ---p 00000000 00:00 0
    bfba2000-bfbc3000 rw-p 00000000 00:00 0 [stack]
    ABLc54m2O1U/o
    rainbow[0][0]=ABcX6n/XofNGc
    rainbow[0][1]=nXofNGc
    rainbow[0][2]=ABqx7VTBarsSg
    rainbow[0][3]=VTBarsSg
    rainbow[0][4]=ABSsnjWVtu9YI
    .
    .
    .
    rainbow[9][1]=dU7fF46
    rainbow[9][2]=ABL2KPL.QWYj.
    rainbow[9][3]=PLQWYj
    rainbow[9][4]=ABXIo/MRLE2F.
    make: *** [test] Przerwane
0

Na początku h wskazuje na zaalokowaną pamięć:
char *h = (char *) malloc(DES_CHARS_NUM * sizeof (char));

później w pętli for przypisujesz do h wynik hash:
h = (char ) hash((wordstab + j))

a na końcu próbujesz usunąć:
free(h)

Spróbuj w pętli for przechowywać wynik hash w innej zmiennej, aby h wskazywało cały czas na pamięć zaalokowaną na początku funkcji.

0

Problem masz już rozwiązany. Ja tylko w kwestii formalnej:

eaglefly napisał(a)
    char ***rainbowtab = (char ***) malloc(n * sizeof (char **));
    *(rainbowtab + i) = (char **) malloc(deep * sizeof (char *));

"char**" niczym się nie różni zbytnio od "char*" czy nawet "int*". Wszystko to są wskaźniki i wszystkie mają ten sam rozmiar:

[beorn@reki tmp]$ cat test.c
#include <stdio.h>

int main(void) {
    fprintf(stdout, "char** - %d\n", sizeof(char**));
    fprintf(stdout, "char* - %d\n", sizeof(char*));
    fprintf(stdout, "char - %d\n", sizeof(char));
    return 0;
}
[beorn@reki tmp]$ ./test
char** - 8
char* - 8
char - 1

To tak na wypadek gdybyś był przekonany, że sizeof(char**) zaalokuje Ci więcej pamięci.

0

Dzięki za odpowiedzi. Nie wiem czy dobrze zastosowałem się do porad, ponieważ problemu dalej nie rozwiązałem.

Funkcja hash;

 
char *hash(char *password) {

    char salt[3] = "AB";

    if (strcmp(password, "") == 0) {
        fprintf(stderr, "Nie podano hasza, ktore ma byc poddane haszowaniu!");
        return NULL;
    }

    password= crypt(password, salt);

    return password;
}

Funkcja createTable:

 char*** createRainbowTable(char **wordstab, int deep, int n) {
    int i;
    int j;
    char *h;
    char *r;

    /*Alokacja pamięci dla tablicy*/
    char ***rainbowtab = (char ***) malloc(n * sizeof (char **));

    for (i = 0; i < n; i++) {
        *(rainbowtab + i) = (char **) malloc(deep * sizeof (char *));
        for (j = 0; j < deep; j++)
            *(*(rainbowtab + i) + j) = (char *) malloc(DES_CHARS_NUM * sizeof (char));
    }

    if (rainbowtab == NULL) {
        fprintf(stderr, "Nie mozna przydzielic pamieci 05");
        return NULL;
    }

    char *tmp;
    for (j = 0; j < n; j++) {

        for (i = 0; i < deep; i++) {

            if (i == 0) {
                h = (char *) hash(*(wordstab + j));
            }

            if (i > 0 && i % 2 == 0) {
                h = (char *) hash(r);
            }

            if (i % 2 != 0) {
                r = (char *) reduce(h);
            }

            if (i == deep - 1) {
                tmp = hash(r);
                rainbowtab[j][1] = tmp;
                printf("tmp[%d]: %s\n", j, rainbowtab[j][1]);
            }
        }

        rainbowtab[j][0] = *(wordstab + j);
    }

    for (i = 0; i < n; i++) {
        printf("tab[%d]: %s\n", i, rainbowtab[i][1]);
    }

    return rainbowtab;
} 

Chodzi mi o to, że jako wynik otrzymuję w tym samym elemencie tablicy różne wartości. Wiem, że w jakiś sposób przypisuję wszystkie elementy tablicy do jednego adresu, ale nie wiem jak sprawić, żeby tak się nie działo.

Poniżej dołączam jeszcze output. Moim celem jest to, żeby takie wyniki jak w 'tmp' były w 'tab':

 ./rainbowtab
tmp[0]: ABSsnjWVtu9YI
tmp[1]: ABPmwY3GSNwGY
tmp[2]: ABtVk16.qhie.
tmp[3]: ABdFeUiaA9XWM
tmp[4]: ABtVk16.qhie.
tmp[5]: ABeXdbEVfdDMQ
tmp[6]: ABaUegj6VPj36
tmp[7]: AB/ugxQ99wRj.
tmp[8]: ABRfDOHv6xfRI
tmp[9]: ABXIo/MRLE2F.
tab[0]: ABXIo/MRLE2F.
tab[1]: ABXIo/MRLE2F.
tab[2]: ABXIo/MRLE2F.
tab[3]: ABXIo/MRLE2F.
tab[4]: ABXIo/MRLE2F.
tab[5]: ABXIo/MRLE2F.
tab[6]: ABXIo/MRLE2F.
tab[7]: ABXIo/MRLE2F.
tab[8]: ABXIo/MRLE2F.
tab[9]: ABXIo/MRLE2F.
1

Odpowiedź jest prosta, funkcja crypt zwraca ci wskaźnik na pamięć globalną (lub static w funkcji).
Rozwiązanie:
password=strdup(crypt(password,salt));
ale nie przydzielaj pamięć do drugiego wymiaru:
for (j = 0; j < deep; j++)
((rainbowtab + i) + j) = (char *) malloc(DES_CHARS_NUM * sizeof (char));
lub zamiast podmiany wskaźnika:
rainbowtab[j][1] = tmp;
skopiuj napis:
strcpy(rainbowtab[j][1],tmp);

0

Jesteś kotem. Dzięki za odpowiedź:)

1 użytkowników online, w tym zalogowanych: 0, gości: 1