Błąd podczas zwalniania dynamicznie alokowanej tablicy

0

Ok tamto zostało rozwiązanie teraz mam problem ze zwalnianiem pamięci po tablicy. Wyskakuje mi błąd.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define lenght 100
#define pointer_size 2
#define word_lenght 20

int main()
{
    char white_chars[8] = " ,.-'\n'";
    char **words =(char**) malloc(sizeof(*words));
    words[0] = (char *)malloc(word_lenght * sizeof(**words));

    char *token;    // wskaznik na token, czyli adres tam gdzie ześmy skończyli. np zdanie :"p ha", po wykonaniu funkcji strtok token bedzie wskazywać na adres gdzie jest "h"
    char sentence[lenght];
    fgets(sentence, lenght, stdin);
    printf("%s", sentence);

    words[0] = strtok_s(sentence, white_chars, &token); // pobranie 1 słowa
    printf("1: %s\n", words[0]);
    int i = 0;
    while (words[i] != NULL)
    {
        i++;
        words = (char**)realloc(words, (i+1)*sizeof(*words));
        words[i] = (char *)malloc(word_lenght * sizeof(**words));
        words[i] = strtok_s(NULL, white_chars, &token);
        if (words[i] != NULL)
        {
            printf("%d: %s\n", i + 1, words[i]);
        }
        else
        {
            words[i] = NULL;
        }
    }

    getch();
    return 0;
}
1
words[0] = (char *)malloc(word_lenght * sizeof(**words));//Wskaźnik zajmuje 4 bajty, więc tak właściwie alokujesz obszar o rozmiarze 80 bajtów
* words = (char *) malloc(word_length * sizeof(char));//Tak powinno być.

No i jeszcze jedna mała uwaga: nazwy stałych powinieneś pisać wielkimi literami, np.:

#define WORD_LENGTH 20 

Każda re-alokacja zabiera trochę czasu. Czy nie efektywniej byłoby najpierw zliczyć wyrazy, by potem zaalokować raz, ale odpowiednią ilość pamięci na wskaźniki na wyrazy? Potem tylko wyodrębniać wyrazy i zapisywać je do tej dynamicznej tablicy.
No i te białe znaki to dla nich tablica jest za mała, jak w ten sposób chcesz je podać. Usuń liczbę z nawiasów kwadratowych, to kompilator sam obliczy, ile miejsca potrzebuje. Zapewne chciałeś dodać sam znak nowej linii, więc nie potrzebujesz apostrofów przed i za znakiem nowej linii. Jest on traktowany jako jeden znak i wystarczy samo \n pomiędzy nawiasami bez znaków cudzysłowu.

EDIT: Jak chcesz zwolnić pamięć, to najpierw musisz zwolnić pamięć wskazywaną przez wskaźniki, a następnie pamięć wskazywaną przez wskaźnik na wskaźniki. Może ogólniej:

#define ILOSC_WYRAZOW 3
#define DLUGOSC_WYRAZU 5
//... 
    char ** tab;//tablica dwuwymiarowa
    int i;//licznik
    tab = (char **) malloc(ILOSC_WYRAZOW * sizeof(char *));//alokowanie pamięci na wskaźniki na ciągi znaków
    for(i = 0; i < ILOSC_WYRAZOW; i++)
        *(tab + i) = (char *) malloc(DLUGOSC_WYRAZU * sizeof(char));//alokowanie pamięci na wyrazy

    for(i = 0; i < ILOSC_WYRAZOW; i++)
        free(*(tab + i));
    free(tab);
0

Allokujesz pamięć:


    words[0] = (char *)malloc(word_lenght * sizeof(**words));
 

by zaraz stracić wskaźnik do tej pamięci....

     words[0] = strtok_s(sentence, white_chars, &token); // pobranie 1 słowa
0

Przy takim zwalnianiu wyskakuje błąd:

screen.jpeg

    while (i >= 0)
    {
        free(words[i]);
        i--;
    }
    free(words);

oczywiście i jest ze wcześniejszej pętli.

Zmieniłem tablice sentence na taką:

char *sentence = (char*)malloc(LENGHT*sizeof(char));

i zgodnie z tym jak funkcja strtok działa wystarczy:

free(sentence);
free(words)

dodanie obrazka do załączników i treści posta - @furious programming

0

Jeśli nie zmieniłeś programu, to prawidłowo, że się wywala - patrz mój post wyżej.

0

Aktualnie wygląda tak:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define LENGHT 100
#define word_lenght 20

int main()
{
    char white_chars[8] = " ,.-'\n'";
    char **words = (char**)malloc(sizeof(*words));

    char *token;    // wskaznik na token, czyli adres tam gdzie ześmy skończyli. np zdanie :"p ha", po wykonaniu funkcji strtok token bedzie wskazywać na adres gdzie jest "h"
    char *sentence = (char*)malloc(LENGHT*sizeof(char));
    fgets(sentence, LENGHT, stdin);
    printf("%s", sentence);

    words[0] = strtok_s(sentence, white_chars, &token); // pobranie 1 słowa
    printf("1: %s\n", words[0]);
    int i = 0;
    while (words[i] != NULL)
    {
        i++;
        words = (char**)realloc(words, (i + 1)*sizeof(*words));// realokacja tablicy wskażników
        words[i] = strtok_s(NULL, white_chars, &token);// funkcja zwraca adres na początek slowa i aż do jego końca char *strtok
        if (words[i] != NULL)
        {
            printf("%d: %s\n", i + 1, words[i]);
        }
    }
    free(sentence);
    free(words);

    getch();
    return 0;
}

i tutaj się wywala:


   while (i >= 0)
    {
        free(words[i]);
        i--;
    }
    free(words);

I tak myślę. Bo words[i] są częściami sentence, więc nie mogę zwolnić jakieś części pamięci w sentence. Więc muszę wyrzucić sentence , by zwolnić pamięć.
Czy dobrze rozumiem ?

0

bo to drugie zwalnianie jest bez sensu - tam gdzie nie przydzielasz pamięci, to jej nie zwalniaj!
Druga rzecz - nieoptymalnie jest robić częste realloki...

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