结构数组中的值变为垃圾值

时间:2011-10-01 23:18:40

标签: c arrays struct

我有一个让我感到困惑的问题......下面我正在调用初始化函数:

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;
}

它似乎工作,我在循环中打印值,这很好。如果我也在main中打印一个相同的循环来进行双重检查它也可以正常工作但是如果我只是在initialize函数之后打印main中的值(在Initialize中没有print语句)我得到完全垃圾。

似乎我存储我的价值的记忆并不是保持一致,我无法弄清楚原因。

我是否需要malloc内存用于结构?由于我不需要可变数量的存储,我认为没有必要...我不确定如何去做。

我的结构:

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;

我只是从main调用Initialize:

int main () {
    List *newList;

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

return 0;
}

callInitialize:

List *callInitialize () {
List *L;

List studentList;
L = &studentList;

Initialize(L); 

return L;
}

2 个答案:

答案 0 :(得分:5)

现在您发布了导致实际问题的函数,我们看到了什么错误:您正在返回超出范围的局部变量的地址!这是无效的。

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!!
}

您的情况需要动态(或“手动”)分配,这意味着内存分配的生命周期仅由控制,而不是由本地范围控制。< / p>

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

任何手动分配都需要清理程序:

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

答案 1 :(得分:4)

现在您已经发布了剩余的代码,问题显而易见:

List *callInitialize () {
    List *L;

    List studentList;
    L = &studentList;

    Initialize(L); 

    return L;
}

在此函数中,您可以创建一个局部变量studentList,然后传递给Initialize进行设置。

不幸的是,当您退出studentList函数时,callInitialize变量的范围结束。这就是为什么当你以后尝试使用垃圾时它可能含有垃圾。

尽管你的评论不需要malloc,因为结构很小,如果你希望数据的范围超出它创建的函数,你需要它。

可能“最小变化”的解决方案是:

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

然后记住调用者需要在某个时候释放它,除非malloc失败并且此函数因此返回NULL。