• 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.

0 głosów
771 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 (195,240 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ź 232 wizyt
0 głosów
1 odpowiedź 473 wizyt
0 głosów
1 odpowiedź 565 wizyt
pytanie zadane 30 października 2022 w C i C++ przez DonPatricio Nowicjusz (150 p.)

93,424 zapytań

142,420 odpowiedzi

322,637 komentarzy

62,782 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

VMware Cloud PRO - przenieś swoją infrastrukturę IT do chmury
...