Search code examples
cpointersreturn

Why does the returned array differ from the array that uses the return value in my program?


I have a program where I want to add a new element into an array of structs. In my add function it seems to be working, but when I try to use it in the main function, it seems to differ from what's being originally returned.

I have my main.c like this:

int main(void) {
    Recept * receptek;
    int valasztas;
    int *hossz = 0; //A receptek száma.
    receptek = betolt("receptek.txt", &hossz);
    if (receptek != NULL) {
        menu();
        printf("Valasztott opcio: ");
        while(scanf("%d", &valasztas) == 1) {
            if(valasztas == 1) {
                Recept * uj = recept_felvesz(receptek, hossz);
                printf("%dTH VALUE HERE: %s\n", (int)hossz, uj[(int)hossz].nev);
                if(uj != NULL) {
                    printf("Recept sikeresen felveve.\n\n");
                    hossz = (int)hossz + 1;
                } else {
                    printf("Nem sikerult a receptet felvenni.\n\n");
                }
            } else if(valasztas == 2) {

                kiir(receptek, (int)hossz);
            } else if(valasztas == 6) {
                break;
            } else {
                system("cls");
                menu();
                printf("Ervenytelen opcio.\n\n");

            }
            printf("Valasztott opcio: ");
        }
    } else {
        printf("Nem sikerult betolteni a tarolofajlt!\n");
    }
  return 0;
}

And I store my add function (recept_felvesz) in a different .h file.

Recept* recept_felvesz(Recept* receptek, int* hossz) {
    printf("Hossz 1: %d", (int)hossz);
    setbuf(stdin, NULL);
    char bekert_nev[30];
    char bekert_ot[300];
    printf("Add meg a recept nevet: ");
    if(fgets(bekert_nev, 30, stdin))
        bekert_nev[strcspn(bekert_nev, "\n")] = '\0';   //A \n karaktert kicseréli \0-ra
    printf("Add meg a recept osszetevoit: ");
    if(fgets(bekert_ot, 300, stdin))
        bekert_ot[strcspn(bekert_ot, "\n")] = '\0';     //A \n karaktert kicseréli \0-ra.
    system("cls");
    menu();

    Recept uj = {(int)hossz, bekert_nev, bekert_ot};
    receptek = (Recept*) realloc(receptek, ((int)hossz + 1) * sizeof(Recept));
    receptek[(int)hossz] = uj;

    if (receptek == NULL) return NULL;

    FILE *file = fopen("receptek.txt", "a");
    if (file == NULL) return NULL;

    fprintf(file, "\n%s;%s;", bekert_nev, bekert_ot);
    fclose(file);
    printf("\n%dTH VALUE HERE: %s\n", (int)hossz, receptek[(int)hossz].nev);
    return receptek;
}

Here is the buggy output at the moment:

15TH VALUE HERE: 32423
15TH VALUE HERE: ☺
Recept sikeresen felveve.

Why does the actual return value (32423) differ from what's being used in the main function()?

Edit: structure Recept looks like this:

typedef struct Recept {
    int azonosito;
    char *nev;
    char *osszetevok;
} Recept;

Solution

  • In this code memory of local variables bekert_nev and bekert_ot are used outside of the scope where they are defined (function recept_felvesz). They are allocated on stack so after exit from function recept_felvesz their memory can be used by anyone else as it is considered unused. For example printf can store its internal variables in this memory block.

    One way to fix this issue is to allocate bekert_nev and bekert_ot in global memory using malloc function:

    char* bekert_nev = malloc(30);
    char* bekert_ot = malloc(300);
    

    Remember to free this memory with free function when you will destroy your main receptek array:

    Recept* rec = receptek;
    for( int i = 0; i < hossz; ++i) {
      free( rec->nev );
      free( rec->osszetevok );
      rec++;
    }
    

    Alternatively, you can put this arrays inside of your Recept struct and write directly into them

    typedef struct Recept {
        int azonosito;
        char nev[30];
        char osszetevok[300];
    } Recept;