• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

question-closed Wczytywanie danych z pliku, problem przy ograniczeniu wielkości sterty.

Object Storage Arubacloud
0 głosów
562 wizyt
pytanie zadane 2 lipca 2020 w C i C++ przez pozdro600 Początkujący (260 p.)
zamknięte 16 sierpnia 2020 przez pozdro600

Funkcja:

int load(const char* filename, int*** ptr, enum save_format_t format)

ma za zadanie wczytać dane z pliku .txt lub .bin(zaleznie od wartosci zmiennej format: 0 lub 1)do macierzy. Dane w pliku zapisane są np. w taki sposób: 

10 20 30 40 50 60 70 -1
100 200 300 400 500 600 700 800 -1

tzn. kazdy wiersz ma kończyć się '-1'. Dane mają zostać zapisane do macierzy razem z '-1'. Wskaznik na wiersz po ostatnim zapełnionym wierszu macierzy ma być równy NULL. Dla danych zawartych w pliku powyzej, wygląda to tak:

int A[] = {10, 20, 30, 40, 50, 60, 70, -1};
int B[] = {100, 200, 300, 400, 500, 600, 700, 800, -1};
int* D[] = {A, B, C, NULL};

Oto dodatkowe objaśnienie wyjęte z treści zadania:

Funkcja wczytująca dane z pliku o nazwie filename.

Parametry:

ptr - adres wskaźnika do którego ma zostać zapisany adres zbioru danych odczytany z pliku filename,
format - flaga formatu w jakim dany plik ma być wczytany (fmt_text lub fmt_binary).

W funkcji należy zaalokować tylko tyle pamięci ile będzie potrzebne na przechowanie całego zbioru danych.

Wartość zwracana:

1 - w przypadku błędnych danych wejściowych,
2 - jeżeli plik nie istnieje,
3 - jeżeli dane w pliku są niepoprawne,
4 - jeżeli nie udało się przydzielić pamięci na którymkolwiek z etapów wczytywania pliku danych.
0 - w przypadku poprawnego odczytania danych.


Pamiętaj, aby w przypadku stwierdzenia braku pamięci (kod 4) zwolnić całą przydzieloną wcześniej pamięć. Funkcja load nie może generować wycieków pamięci.

Testy przeprowadzone na mojej funkcji z limitem sterty wyświetlają błąd: 

Sprawdzanie poprawności działania funkcji load (limit sterty ustawiono na 348 bajtów)⏎
Analiza zasobów: PORAŻKA: Wykryto naruszenie granic bloku pamięci. [Uszkodzony został blok zaalokowany w "*ptr = (int**)malloc(sizeof(int*) * h);" a samo uszkodzenie zauważono w trakcie wykonywania " *(*ptr + i) = (int*)malloc(sizeof(int) * w);". Opis: Wykryto modyfikację obszaru pamięci za zaalokowanym blokiem (RVE_INVALID_TAIL_FENCE)].

Próbowałem na wiele sposobów obejść problem i nie udaje mi się. Czy ktoś wie, jak mogę go rozwiązać?

Oto moja funkcja:

int load(const char* filename, int*** ptr, enum save_format_t format) {
    if (filename == NULL || ptr == NULL || format != 0 && format != 1 ) {
        return 1;
    }
    int val = 0;
    FILE* fp, * pp;
    if (format == 0) {
        int i = 0, x = 0, h = 0, w = 0;
        fp = fopen(filename, "r");
        if (fp == NULL) {
            return 2;
        }
        pp = fopen(filename, "r");
        if (pp == NULL) {
            fclose(fp);
            return 2;
        }
        int val2 = 0;
        while (1)
        {
            if (fscanf(fp, "%d", &val2) == EOF) {
                if (val != -1 && i != 0) {
                    fclose(fp);
                    fclose(pp);
                    return 3;
                }
                break;
            }
            val = val2;
            if (val == -1)
            {
                h++;
            }
            i++;
        }
        if (i == h) {
            fclose(fp);
            fclose(pp);
            return 3;
        }
        i = 0;
        fseek(fp, 0, SEEK_SET);
        *ptr = (int**)malloc(sizeof(int*) * h);
        if (*ptr == NULL) {
            fclose(fp);
            fclose(pp);
            return 4;
        }
        *(*ptr + h) = NULL;
        for (i = 0; i < h; i++) {
            val = 0, w = 0;
            while (val != -1)
            {
                if (fscanf(pp, "%d", &val) == EOF) {
                    break;
                }
                w++;
            }
            *(*ptr + i) = (int*)malloc(sizeof(int) * w);
            if (*(*ptr + i) == NULL) {
                for (int s = 0; s < i; s++) {
                    free(*(*ptr + s));
                }
                free(*ptr);
                fclose(pp);
                fclose(fp);
                return 4;
            }

            for (x = 0; x < w; x++) {
                fscanf(fp, "%d", *(*ptr + i) + x);
            }
        }
        fclose(fp);
        fclose(pp);
    }
    else if (format == 1) {
        int i = 0, x = 0, h = 0, w = 0;
        fp = fopen(filename, "r");
        if (fp == NULL) {
            return 2;
        }
        pp = fopen(filename, "r");
        if (pp == NULL) {
            fclose(fp);
            return 2;
        }
        int val2 = 0;
        while (1)
        {
            if (fread(&val2, sizeof(int), 1, fp) == 0) {
                if (val != -1 && i != 0) {
                    fclose(fp);
                    fclose(pp);
                    return 3;
                }
                break;
            }
            val = val2;
            if (val == -1)
            {
                h++;
            }
            i++;
        }
        if (i == h) {
            fclose(fp);
            fclose(pp);
            return 3;
        }
        i = 0;
        fseek(fp, 0, SEEK_SET);
        *ptr = (int**)malloc(sizeof(int*) * h);
        if (*ptr == NULL) {
            fclose(fp);
            return 4;
        }
        *(*ptr + h) = NULL;
        for (i = 0; i < h; i++) {
            val = 0, w = 0;
            while (val != -1)
            {
                fread(&val, sizeof(int), 1, pp);
                w++;
            }
            *(*ptr + i) = (int*)malloc(sizeof(int) * w);
            if (*(*ptr + i) == NULL) {
                for (int s = 0; s < i; s++) {
                    free(*(*ptr + s));
                }
                free(*ptr);
                fclose(pp);
                fclose(fp);
                return 4;
            }
            for (x = 0; x < w; x++) {
                if (fread((*(*ptr + i) + x), sizeof(int), 1, fp) == 0) {
                    fclose(fp);
                    return 2;
                }
            }
        }
        fclose(fp);
        fclose(pp);
    }
    return 0;
}

 

zamknięte
1
komentarz 16 sierpnia 2020 przez ScriptyChris Mędrzec (190,190 p.)

@pozdro600, dlaczego edytowałeś temat do nieczytelnej formy?

1 odpowiedź

0 głosów
odpowiedź 2 lipca 2020 przez j23 Mędrzec (194,920 p.)
edycja 3 lipca 2020 przez j23

Po co otwierasz dwa razy ten sam plik?

if (... format != 0 && format != 1 ) 
...
if (format == 0) 
...
else if (format == 1) 
...

Po to format jest typu wyliczeniowego, żebyś nie stosował magicznych liczb.

Czytanie można uprościć do:

int read_value(FILE *file, int *value, enum save_format_t fmt)
{
	switch (fmt) {
	case fmt_text: return fscanf(file, "%d", value);
	case fmt_binary: return fread(value, sizeof(int), 1, fp);
	};
	return 0;	
}


...

int val;
int **tab = malloc(sizeof(int*));
size_t tab_size = 0;
int * row = NULL;
size_t row_size = 0;

tab[tab_size] = NULL;

while(read_value(fp, &val, format) == 1) {
	int * tmp_row = realloc(row, sizeof(int) * (row_size + 1));
	if(tmp_row == NULL) {
		free(row);
		// zwalniasz tablicę 'tab' jakąś funkcją np. free_tab
		return 4;
	}

	row = tmp_row;
	row[row_size++] = val;
	if(val == -1) {
		int** tmp_tab = realloc(tab, sizeof(int*) * (tab_size + 1 + 1));
		if(tmp_tab == NULL) {
			// zwalniasz tablicę 'tab' jakąś funkcją np. free_tab
			return 4;
		}

		tab = tmp_tab;
		tab[tab_size++] = row;
		tab[tab_size] = NULL;
		row = NULL;
		row_size = 0;
	}
}

 

Podobne pytania

0 głosów
1 odpowiedź 182 wizyt
0 głosów
1 odpowiedź 309 wizyt
0 głosów
1 odpowiedź 283 wizyt
pytanie zadane 30 października 2022 w C i C++ przez DonPatricio Nowicjusz (150 p.)

92,572 zapytań

141,423 odpowiedzi

319,645 komentarzy

61,959 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...