开发者

Values in array of structs turning into garbage values

开发者 https://www.devze.com 2023-04-10 04:48 出处:网络
I have an issue that\'s really confusing me... Below I am calling an initialize function: void Initialize (List *L) {

I have an issue that's really confusing me... Below I am calling an initialize function:

void Initialize (List *L) {
    char* initialize = "initialize";
    int i;

    for (i=0; i<MAXLISTSIZE; i++) {
       strncpy(L->items[i].name,initialize,MAXNAMESIZE);
       L->items[i].name[MAXNAMESIZE - 1] = '\0';
       L->items[i].grade = 0;
       printf("L->items[i].name = %s\n", L->items[i].name);
       printf("L->items[i].grade = %d\n", L->items[i].grade);
    }    
    L->count = 0;
}

And it seems to work, I print the values in the loop and it's fine. If I also print inside an identical loop in main to double check it works as well but If I just print the values in main after the initialize function (no print statements in Initialize) I get complete garbage.

It seems the memory I'm storing my values in isn't staying consistent and I can't figure out why.

Do I need to malloc memory for the structs? Since I don't need a variable amount开发者_如何学Python of storage I thought it was not necessary... I am unsure of how to go about that.

My Structs:

typedef Student Item;
#define MAXLISTSIZE 4
typedef struct {
Item items[MAXLISTSIZE];
int count;
} List;

#define MAXNAMESIZE 20
typedef struct {
char name[MAXNAMESIZE];
int grade;   
} Student;

I am simply calling Initialize from main:

int main () {
    List *newList;

    /*call initialize function*/
    newList = callInitialize();

return 0;
}

callInitialize:

List *callInitialize () {
List *L;

List studentList;
L = &studentList;

Initialize(L); 

return L;
}


Now that you posted the function that causes the actual problem, we see what's wrong: You are returning the address of a local variable that goes out of scope! This is not valid.

List * foo()
{
  List x;     // <--- x comes to life
  return &x;  // <--- x dies here...
}

int main()
{
  List * p = foo();  // ... but its address is used here!
  p->name ...        // dereferencing an invalid address!!
}

Your situation calls for dynamic (or "manual") allocation, which means memory allocation whose lifetime is controlled only by you, and not by the local scope.

List * initList()
{
  return malloc(sizeof(List)); // this memory is permanent
}

Any manual allocation needs to come with a clean-up routine:

void freeList(List * p)
{
  free(p);
}


Now that you've posted the remainder of your code, the problem is obvious:

List *callInitialize () {
    List *L;

    List studentList;
    L = &studentList;

    Initialize(L); 

    return L;
}

Within this function you create a local variable studentList which you the pass to Initialize to set it up.

Unfortunately, the scope of the studentList variable ends when you exit the callInitialize function. That's why it may contain rubbish when you attempt to use it later on.

Despite your comment about not needing malloc because the structure is small, you do need it if you want the scope of the data to exist beyond the function it's created in.

Probably the "minimal-change" solution would be:

List *callInitialize (void) {
    List *L = malloc (sizeof (List));
    if (L != NULL)
        Initialize(&L); 
    return L;
}

and then remember that it needs to be freed at some point by the caller, unless the malloc fails and this function therefore returns NULL.

0

精彩评论

暂无评论...
验证码 换一张
取 消