[c] nieprawidłowe zwalnianie pamięci - pytania

0

Mam za sobą semestr studiów i po sesji chciałem wzbogacić sobie moje umiejętności programowania i napisałem program. Oczywiście wynikły błędy najprawdopodobniej związane z niewłaściwą alokacją, a co bardziej prawdopodobne zwalnianiem pamięci. I tutaj mam kilka pytań:

  1. Co się dzieje z zaalokowaną pamięcią gdy uruchomię sobie program i znudzi mi się albo wpadnie w pętle i nacisnę ctrl+c czyli przerwę jego działanie?
  2. Czy system będzie miał kiedykolwiek dostęp do pamięci, która nie została na czas zwolniona?
  3. Czy program może mi za pomocą funkcji malloc przydzielić w dwóch miejscach wywołania tą samą pamięć? Bo w ciągu jednej instrukcji zmienia mi się wartość w dwóch miejscach w dobrym i jeszcze jakimś innym.
0
  1. Co się dzieje z zaalokowaną pamięcią gdy uruchomię sobie program i znudzi mi się albo wpadnie w pętle i nacisnę ctrl+c czyli przerwę jego działanie?
  2. Czy system będzie miał kiedykolwiek dostęp do pamięci, która nie została na czas zwolniona?

System "wie" że proces zaalokował pamięć i po wyładowaniu procesu zwalniana jest również jego pamięć. Szczegółów technicznych dot. zarządzania pamięcią przez Windows niestety nie znam.

  1. Czy program może mi za pomocą funkcji malloc przydzielić w dwóch miejscach wywołania tą samą pamięć? Bo w ciągu jednej instrukcji zmienia mi się wartość w dwóch miejscach w dobrym i jeszcze jakimś innym.

To brzmi ciekawie, ale aż nie chce mi się wierzyć. W skrócie - nie może. Chyba że masz niewiarygodnego pecha i trafiłeś na jakiegoś buga, ale to zakrawa na niemożliwość.

0

Po prostu robię malloca na char* i strcpy. Po tych dwóch instrukcjach kopiowany napis zostaje dopisany w dwóch miejscach, ale mam zamiar się zgłosić w przyszłym tygodniu do jakiegoś korepetytora, w każdym razie mi się wydaje, że ten komplet instrukcji wykonuje się raz(używałem debuggera), ale nie wrzucam kodu, bo strasznie długi jest ten cały program(oczywiście jeśli ewentualnie ktoś chce pomóc to mogę wrzucić).

0

struktury

 
typedef struct {
	char *imie;
	char *nazwisko;
        int rok_ur;
	char * pesel;
	char* grupa;
	char* zajecia;
} dziecko_t;

typedef struct {
	dziecko_t * lista_dzieci;
	int n;
	int wielkosc;
}
list_t;

typedef struct {
	char** pesele;
	char *nazwa;
	int ilosc;
	int wielk;
}
grupa_t;

typedef struct {
	grupa_t * grupa;
	int n;
	int wielkosc;
}
grupy_t;

main

void menu(int *n ) {
        if( *n != 5 ) {
            printf("\nMenu 1:  Wyjdz2: \n" );
            scanf( "%d", n );
        }
        if( *n == 1 )
        printf( "\n\n1. Wyswietl.\n  1.1. Dzieci.\n  1.2 Grupy.\n    1.2.1. Wszystkie.\n    1.2.2. Pojedyncza\n  1.3. Zajecia dodatkowe.\n    1.3.1. Wszystkie.\n    1.3.2. Pojedyncze\n    1.3.3. Brak zajec\n2. Dodaj.\n  2.1. Dzieci.\n  2.2. Grupy.\n  2.3. Zajecia dodatkowe.\n3. Edytuj.\n  3.1. Dzieci.\n  3.2. Grupy.\n  3.3. Zajecia dodatkowe.\n4. Usun.\n  4.1. Dzieci.\n  4.2. Grupy.\n  4.3. Zajecia dodatkowe.\n5. Koniec\n");
        else
            *n = 5;
}
int main( int argc, char** argv) {
        FILE *wejs = fopen( argv[1], "r" );
        FILE *in = fopen( argv[2], "r" );
        list_t* dzieci = wczytaj_dzieci( wejs );
        grupy_t *grupy = wczytaj_grupy( in );
        if( dolacz_dzieci_do_grup( dzieci, grupy ) == 1 )
              printf( "\n BLAD " );
        if( wypelnij_dziecku_grupe( dzieci, grupy ) )
              printf( "\n BLAD " );
        int n = 0;
        int x;
        int y;
        menu (&n);
        while( n != 5 ) {
            scanf( "%d", &x);
            switch( x ) {
                case 1:
                    printf("Wybrales opcje wyswietl. Wybierz 1. Dzieci 2. Grupy. 3. Zajecia dodatkowe\n");
                    scanf( "%d", &y);
                    switch( y){
                        case 1:
                            wypisz_dzieci(stdout, dzieci);
                            break;
                        case 2:
                            printf(" 1. Wszystkie 2. Pojedyncza");
                            scanf("%d", &y);
                            if( y == 1)
                                wypisz_grupy( stdout, grupy, dzieci);
                            else if( y == 2)
                                wypisz_pojedyncza_grupe( stdout, grupy);
                            else
                                printf("Nie ma takiej opcji");
                            break;
                        case 3:
                            printf(" 1. Wszystkie 2. Pojedyncza");
                            scanf("%d", &y);
                            if( y == 1)
                                printf("Jeszcze nie powstala");
                            else if( y == 2)
                                printf("Jeszcze nie powstala");
                            else if( y == 3)
                                printf("Jeszcze nie powstala");
                            else
                                printf("Nie ma takiej opcji");
                            break;
                        default:
                            printf("Nie ma takiej opcji");
                            break;
                    }
                    break;
                case 2:
                    printf("Wybrales opcje Dodaj. Wybierz 1. Dzieci 2. Grupy 3. Zajecia dodatkowe\n");
                    scanf("%d", &y);
                    switch( y ) {
                        case 1:
                            printf("[Pesel] [Imie] [Nazwisko] [Grupa]\n");
                            dodaj_dzieci( dzieci, grupy);
                            break;
                        case 2:
                            if( dodaj_grupy( grupy ) ) {
                                printf("Blad");
                                return 1;
                            }
                            break;
                        case 3:
                            printf("Jeszcze nie powstala");
                            break;
                        default:
                            printf("Nie ma takiej opcji");
                            break;
                    }
                    break;
                case 3:
                    printf("Wybrales opcje Edytuj: Wybierz 1. Dzieci 2. Grupy 3. Zajecia dodatkowe\n");
                    scanf("%d", &y);
                    switch( y ) {
                        case 1:
                            edytuj_dziecko( dzieci, grupy );
                            break;                                                                                                                                                   
                        case 2:
                            printf("Jeszcze nie powstala");                                                                                                                              
                            break;
                        case 3:
                            printf("Jeszcze nie powstala");
                            break;
                        default:
                            printf("Nie ma takiej opcji");                                                                                                                               
                            break;
                    }
                    break;
                case 4:
                    printf("Wybrales opcje Usun: Wybierz 1. Dzieci 2. Grupy 3. Zajecia dodatkowe\n");
                    scanf("%d", &y);
                    switch( y ) {
                        case 1:
                            usun_dziecko( dzieci, grupy );
                            break;
                        case 2:
                            usun_grupe( dzieci, grupy );
                            break;
                        case 3:
                            printf("Jeszcze nie powstala");
                            break;
                        default:
                            printf("Nie ma takiej opcji");
                            break;
                    }
                    break;
                case 5:
                    n = 5;
                    break;
                default:
                    printf("Nie ma takiej opcji");
                    break;
            }
        menu( &n );
        }
        printf("\n Koniec dzialania programu");
        free_grupy( grupy );
        free_grupki( grupy );
        free_dziecko( dzieci->lista_dzieci);
        free_dzieci( dzieci );
        return 0;
}

 

funkcje

void iniciuj_grupy(grupy_t * e)
{
    e->grupa = malloc(INIT_SIZE * sizeof *e->grupa);
    e->wielkosc = INIT_SIZE;
    e->n = 0;
}
void iniciuj_liste(list_t * dzieci)
{
    dzieci->lista_dzieci = malloc(INIT_SIZE * sizeof *dzieci->lista_dzieci);
    dzieci->wielkosc = INIT_SIZE;
    dzieci->n = 0;
}
int dodaj_dzieci(list_t * l, grupy_t * g)
{
    int   i, flaga = 0;
    char  pesel[12];
    char  imie[MAX];
    char  nazwisko[MAX];
    char  grupa[MAX];
    if (scanf("%s %s %s %s", pesel, imie, nazwisko, grupa) == 4)
    {
        if (dodaj_dziecko(l, imie, nazwisko, pesel))
            printf("Nie udalo sie dodac dziecka");
        else
        {
            for (i = 0; i < g->n; i++)
            {
                g->grupa += i;
                if (strcmp(grupa, g->grupa->nazwa) == 0)
                {
                    l->lista_dzieci += l->n - 1;
                    if ((l->lista_dzieci->grupa = malloc(strlen(grupa) + 1)) == NULL)
                    {
                        l->lista_dzieci -= l->n - 1;
                        g->grupa -= i;
                        return 1;
                    }
                    strcpy(l->lista_dzieci->grupa, grupa);
                    g->grupa -= i;
                    if (dodaj_pesel(g, l->lista_dzieci->grupa, l->lista_dzieci->pesel))
                    {
                        l->lista_dzieci -= l->n - 1;
                        return 1;
                    }
                    g->grupa += i;
                    l->lista_dzieci -= l->n - 1;
                    flaga = 1;
                }
                g->grupa -= i;
            }
            if (flaga == 0)
            {
                printf("Nie ma takiej grupy ");
                wypelnij_dziecku_grupe(l, g);
            }
        }
    }
    else
        printf("Podales za malo");
    return 0;
}
int dodaj_dzieci_edytuj(list_t * l, grupy_t * g, char *pesel, char *imie, char *nazwisko, char *grupa)
{
    int i, flaga = 0;
    if (dodaj_dziecko(l, imie, nazwisko, pesel))
    {
        printf("Nie udalo sie dodac dziecka");
    }
    else
    {
        for (i = 0; i < g->n; i++)
        {
            g->grupa += i;
            if (strcmp(grupa, g->grupa->nazwa) == 0)
            {
                l->lista_dzieci += l->n - 1;
                if ((l->lista_dzieci->grupa = malloc(strlen(grupa) + 1)) == NULL)
                {
                    g->grupa -= i;
                    return 1;
                }
                strcpy(l->lista_dzieci->grupa, grupa);
                g->grupa -= i;
                if (dodaj_pesel(g, l->lista_dzieci->grupa, l->lista_dzieci->pesel))
                {
                    l->lista_dzieci -= l->n - 1;
                    return 1;
                }
                g->grupa += i;
                l->lista_dzieci -= l->n - 1;
                flaga = 1;
            }
            g->grupa -= i;
        }
        if (flaga == 0)
        {
            printf("Nie ma takiej grupy ");
            wypelnij_dziecku_grupe(l, g);
        }
    }
    return 0;
}
int wypelnij_dziecko(dziecko_t * s, char *i, char *n, char *p)
{
    char  tmp[3];
    if ((s->imie = malloc(strlen(i) + 1)) == NULL)
        return 1;
    strcpy(s->imie, i);
    if ((s->nazwisko = malloc(strlen(n) + 1)) == NULL)
        return 1;
    strcpy(s->nazwisko, n);
    if ((s->pesel = malloc(strlen(p) + 1)) == NULL)
        return 1;
    strcpy(s->pesel, p);
    strncpy(tmp, p, 2);
    s->rok_ur = 1900 + atoi(tmp);
    s->grupa = NULL;
    s->zajecia = NULL;
    return 0;
}
 
int dodaj_pesel(grupy_t * s, char *n, char *p)
{
    int i;
    for (i = 0; i < s->n; i++)
    {
        s->grupa += i;
        if ((strcmp(s->grupa->nazwa, n) == 0))
        {
            if (s->grupa->wielk <= s->grupa->ilosc)
            {
                char **nt = realloc(s->grupa->pesele, (size_t) (s->grupa->wielk) * sizeof *nt);
                if (nt != NULL)
                {
                    s->grupa->pesele = nt;
                    s->grupa->wielk *= 2;
                }
                else
                {
                    s->grupa -= i;
                    return 1;
                }
            }
            if ((s->grupa->pesele[s->grupa->ilosc] = malloc(strlen(p) + 1)) == NULL)
            {
                s->grupa -= i;
                return 1;
            }
            strcpy(s->grupa->pesele[s->grupa->ilosc], p);
            s->grupa->ilosc++;
        }
        s->grupa -= i;
    }
    return 0;
}
int wypelnij_grupe(grupa_t * s, char *n)
{
    if ((s->nazwa = malloc(strlen(n) + 1)) == NULL)
        return 1;
    strcpy(s->nazwa, n);
    if ((s->pesele = malloc(INIT_SIZE * sizeof *s->pesele)) == NULL)
        return 1;
    s->wielk = INIT_SIZE;
    s->ilosc = 0;
    return 0;
}
int dodaj_grupe(grupy_t * f, char *nazwa)
{
    if (f->wielkosc <= f->n)
    {
        grupa_t *nt = realloc(f->grupa, (size_t) (f->wielkosc) * sizeof *nt);
        if (nt != NULL)
        {
            f->grupa = nt;
            f->wielkosc *= 2;
        }
        else
            return 1;
    }
    if (wypelnij_grupe(f->grupa + f->n, nazwa))
        return 1;
    f->n++;
    return 0;
}
int dodaj_grupy(grupy_t * g)
{
    char  nazwa[MAX];
    int i;
    printf("\n Podaj nazwe grupy: \n");
    scanf("%s", nazwa);
    for (i = 0; i < g->n; i++)
    {
        g->grupa += i;
        if (strcmp(g->grupa->nazwa, nazwa) == 0)
        {
            printf("\nNie moze byc dwoch takich samych nazw grup\n");
            g->grupa -= i;
            return 1;
        }
        g->grupa -= i;
    }
    if (dodaj_grupe(g, nazwa))
        return 1;
    return 0;
}
int dodaj_dziecko(list_t * e, char *imie, char *nazw, char *pes)
{
    if (e->wielkosc <= e->n)
    {
        dziecko_t *nt = realloc(e->lista_dzieci, (size_t) (2 * e->wielkosc) * sizeof *nt);
        if (nt != NULL)
        {
            e->lista_dzieci = nt;
            e->wielkosc *= 2;
        }
        else
            return 1;
    }
    if (wypelnij_dziecko(e->lista_dzieci + e->n, imie, nazw, pes))
        return 1;
    e->n++;
    return 0;
}
int dolacz_dzieci_do_grup(list_t * l, grupy_t * g)
{
    int i, j, k;
    for (i = 0; i < g->n; i++)
    {
        g->grupa += i;
        for (j = 0; j < g->grupa->ilosc; j++)
            for (k = 0; k < l->n; k++)
            {
                l->lista_dzieci += k;
                if (strcmp(g->grupa->pesele[j], l->lista_dzieci->pesel) == 0)
                {
                    if ((l->lista_dzieci->grupa = malloc(strlen(g->grupa->nazwa) + 1)) == NULL)
                    {
                        l->lista_dzieci -= k;
                        return 1;
                    }
                    strcpy(l->lista_dzieci->grupa, g->grupa->nazwa);
                }
                l->lista_dzieci -= k;
            }
        g->grupa -= i;
    }
    return 0;
}
int wypelnij_dziecku_grupe(list_t * l, grupy_t * g)
{
    int i, j, flaga = 0;
    char  tmp[MAX];
    for (i = 0; i < l->n; i++)
    {
        l->lista_dzieci += i;
        while (l->lista_dzieci->grupa == NULL)
        {
            printf("\nDziecko %s %s jest bez grupy Wpisz ja \n ", l->lista_dzieci->imie, l->lista_dzieci->nazwisko);
            printf(" Masz do wyboru: \n");
            l->lista_dzieci -= i;
            wypisz_grupy(stdout, g, l);
            l->lista_dzieci += i;
            scanf("%s", tmp);
            for (j = 0; j < g->n; j++)
            {
                g->grupa += j;
                if ((strcmp(g->grupa->nazwa, tmp) == 0))
                {
                    printf("Zostanie dodany pesel do grupy %s", tmp);
                    if ((l->lista_dzieci->grupa = malloc(strlen(tmp) + 1)) == NULL)
                    {
                        l->lista_dzieci -= i;
                        g->grupa -= j;
                        return 1;
                    }
                    strcpy(l->lista_dzieci->grupa, tmp);
                    g->grupa -= j;
                    if (dodaj_pesel(g, l->lista_dzieci->grupa, l->lista_dzieci->pesel))
                    {
                        l->lista_dzieci -= i;
                        return 1;
                    }
                    g->grupa += j;
                    flaga = 1;
                }
                g->grupa -= j;
            }
            if (flaga == 0)
                printf("Nie ma takiej grupy - operacja sie nie udala");
        }
        l->lista_dzieci -= i;
    }
    return 0;
}
int edytuj_dziecko(list_t * l, grupy_t * g)
{
    int n;
    char  pesel[11], imie[MAX], nazwisko[MAX], grupa[MAX];
    wypisz_dzieci(stdout, l);
    printf("\nKtore dziecko chcesz edytowac (Wybierz)\n");
    scanf("%d", &n);
    if (n <= l->n)
    {
        l->lista_dzieci += n - 1;
        printf(" Chcesz edytowac dziecko\n");
        wypisz_dziecko(stdout, l->lista_dzieci);
        l->lista_dzieci -= n - 1;
        printf(" Wpisz nowe dane:\n [pesel] [imie] [nazwisko] [grupa]\n");
        if (scanf("%s %s %s %s", pesel, imie, nazwisko, grupa) != 4)
        {
            printf("Zla ilosc");
            return 1;
        }
        usun_dziecko_edytuj(l, g, n);
        dodaj_dzieci_edytuj(l, g, pesel, imie, nazwisko, grupa);
    }
    else
        printf("Nie ma takiego dziecka\n");
    return 0;
}
grupy_t* wczytaj_grupy(FILE * we)
{
    grupy_t *e = malloc(sizeof *e);
    iniciuj_grupy(e);
    char  pesel[12];
    char    nazwa[MAX];
    int i;
    int flaga = 1;
    while (fscanf(we, "%s", nazwa) == 1)
    {
        if (dodaj_grupe(e, nazwa))
        {
            printf(" Nie udalo sie dodac nazwy\n");
            return e;
        }
        flaga = 1;
        while ((flaga == 1) && (fscanf(we, "%s", pesel) == 1))
        {
            if (pesel[11] == ')')
            {
                pesel[11] = '\0';
                flaga = 0;
            }
            else if ((pesel[0] == '(') && (pesel[12] == ')'))
            {
                for (i = 0; i < 11; i++)
                    pesel[i] = pesel[i + 1];
                pesel[11] = '\0';
                flaga = 0;
            }
            else if ((pesel[0] == '(') && (pesel[1] == ')'))
                flaga = 2;
            else if (pesel[0] == '(')
            {
                for (i = 0; i < 11; i++)
                    pesel[i] = pesel[i + 1];
                pesel[11] = '\0';
            }
            if (flaga != 2)
                if (dodaj_pesel(e, nazwa, pesel))
                {
                    printf("Nie udalo sie dodac peselu");
                    return e;
                }
        }
    }
    return e;
}
list_t * wczytaj_dzieci(FILE * we)
{
    list_t  *e = malloc(sizeof *e);
    iniciuj_liste(e);
    char  pesel[12];
    char  imie[MAX];
    char  nazwisko[MAX];
    while (fscanf(we, "%s %s %s", pesel, imie, nazwisko) == 3)
    {
        if (dodaj_dziecko(e, imie, nazwisko, pesel))
        {
            printf("Nie udalo sie dodac dziecka");
            return e;
        }
    }
    return e;
}
void usun_grupe(list_t * p, grupy_t * g)
{
    int i, j, k;
    char  x[MAX];
    int tmp, flaga = 0;
    printf("\n Ktora grupe chcesz usunac( Wybierz) ");
    wypisz_grupy(stdout, g, p);
    scanf("%s", x);
    for (k = 0; k < g->n; k++)
    {
        g->grupa += k;
        if (strcmp(x, g->grupa->nazwa) == 0)
        {
            tmp = k;
            flaga = 1;
        }
        g->grupa -= k;
    }
    if (flaga)
    {
        g->grupa += tmp;
        for (i = 0; i < g->grupa->ilosc; i++)
            for (j = 0; j < p->n; j++)
            {
                p->lista_dzieci += j;
                if (strcmp(p->lista_dzieci->pesel, g->grupa->pesele[i]) == 0)
                {
                    free(p->lista_dzieci->grupa);
                    p->lista_dzieci->grupa = NULL;
                }
                p->lista_dzieci -= j;
            }
        g->grupa -= tmp;
        g->grupa[tmp] = g->grupa[g->n - 1];
        free(g->grupa + g->n - 1);
        g->n--;
        wypelnij_dziecku_grupe(p, g);
    }
    else
        printf("NIe ma takiej grupy");
}
void usun_dziecko(list_t * p, grupy_t * g)
{
    int i, j, n;
    printf("Ktore dziecko chcesz usunac (Wybierz)\n");
    printf("Do wyboru masz:\n");
    wypisz_dzieci(stdout, p);
    scanf("%d", &n);
    if( n <= p->n )
    {
        p->lista_dzieci += n - 1;
        for( i = 0; i < g->n; i++ )
        {
            g->grupa += i;
            for( j = 0; j < g->grupa->ilosc; j++ )
                if (strcmp(g->grupa->pesele[j], p->lista_dzieci->pesel) == 0)
                {
                    g->grupa->pesele[j] = g->grupa->pesele[g->grupa->ilosc - 1];
                    free(g->grupa->pesele + g->grupa->ilosc - 1);
                    g->grupa->ilosc--;
                }
            g->grupa -= i;
        }
        p->lista_dzieci -= n - 1;
        p->lista_dzieci[n - 1] = p->lista_dzieci[p->n - 1];
        free_dziecko(p->lista_dzieci + p->n - 1);
        p->n--;
    }
    else
        printf("\nNie udalo sie podales zly numer\n");
}
void usun_dziecko_edytuj(list_t * p, grupy_t * g, int n)
{
    int i, j;
    if (n <= p->n)
    {
        p->lista_dzieci += n - 1;
        for (i = 0; i < g->n; i++)
        {
            g->grupa += i;
            for (j = 0; j < g->grupa->ilosc; j++)
                if (strcmp(g->grupa->pesele[j], p->lista_dzieci->pesel) == 0)
                {
                    g->grupa->pesele[j] = g->grupa->pesele[g->grupa->ilosc - 1];
                    free(g->grupa->pesele + g->grupa->ilosc - 1);
                    g->grupa->ilosc--;
                }
            g->grupa -= i;
        }
        p->lista_dzieci -= n - 1;
        p->lista_dzieci[n - 1] = p->lista_dzieci[p->n - 1];
        free_dziecko(p->lista_dzieci + p->n - 1);
        p->n--;
    }
    else
        printf("\nNie udalo sie podales zly numer\n");
}
void free_dzieci(list_t * e)
{
    free(e->lista_dzieci);
    free(e);
}
void free_dziecko(dziecko_t * e)
{
    free(e->imie);
    free(e->nazwisko);
    free(e->pesel);
    free(e->grupa);
}
void free_grupa(grupa_t * p)
{
    free(p->nazwa);
    free(p->pesele);
}
void free_grupy(grupy_t * p)
{
    int i;
    for (i = 0; i < p->n; i++)
    {
        free(p->grupa->nazwa);
        free(p->grupa->pesele);
        p->grupa += 1;
    }
    p->grupa -= p->n;
}
void free_grupki(grupy_t * p)
{
    free(p->grupa);
    free(p);
}
0

Aaaaaa WTF? sformatuj to najpierw normalnie, bo nikt przecież nie będzie tego czytał...

0

@autor: ponad 1000 linii. Myślisz ze ktoś rzuci na to okiem? Wątpliwe...
Jak masz problem z podstawami (a skoro nie umiesz dynamicznie alokować pamięci, to masz) to pisz krótkie (!) programy.

0

A po czym poznałeś, że nie umiem dynamicznie alokować pamięci. Jak już coś piszesz to mógłbyś trochę się przyłożyć, bo nie wiem co mam źle w tym programie. Poza tym pokazałem kod na życzenie, a to że ma tyle ile ma to inna sprawa. Sformatuje kod porządniej za parę godzin, bo chwilowo nie mam czasu.

0

SFORMATUJ KOD.
PS. Gratulacje! Wygrałeś na loterii! Za chwile podam ci sformatowany kod...
PS2 http://4programmers.net/Pastebin/1058

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