【发布时间】:2021-09-22 10:44:32
【问题描述】:
我正在使用 C 语言开发一个小项目,我想在函数中分配结构并将它们添加到结构数组中。
由于某种原因,当我打印结构数组的内容时,我似乎开始从未分配的内存中打印。
下面提供了一个最小的工作示例:
#include <stdio.h>
#include <stdlib.h>
// This struct simply stores a list and its size
struct list {
int* values;
size_t size;
};
// This function initialises an array of lists
// of size len, which each list (i.e. list.values)
// having a size of list_len
// `lists` is an array of pointers to lists
void list_init(struct list** lists, size_t len, size_t list_len) {
for (size_t i = 0; i < len; i++) {
struct list list;
list.values = malloc(sizeof(int) * list_len);
list.size = list_len;
lists[i] = &list;
}
}
void main() {
int len = 3;
struct list* lists[len];
list_init(lists, len, 5);
// Print lists
for (size_t i = 0; i < len; i++) {
printf("list %zu: ", i);
printf("size: %zu\n", lists[i]->size);
for (size_t j = 0; j < 5; j++) { // Using 5 instead of lists[i]->size for obvious reasons
printf("%d ", lists[i]->values[j]);
}
printf("\n");
}
}
我期望的输出是:
list 0: size: 5
0 0 0 0 0
list 1: size: 5
0 0 0 0 0
list 2: size: 5
0 0 0 0 0
但我得到了:
list 0: size: 5
0 0 0 0 0
list 1: size: 140727488332736
0 0 0 0 0
list 2: size: 140727488332736
0 0 0 0 0
这是一个非常明显的信号,表明我正在访问我不应该访问的内存。
我注意到,如果我通过将内存分配给带有struct list* list = malloc(sizeof(struct list)); 的指针来声明列表,程序会给出预期的输出,而不是用struct list list; 声明列表。这是为什么?如果我想创建对象而不是指针,我该如何正确地做到这一点。
P.S.:我知道我可以将 list 初始化为指针。这个问题主要是问为什么不能我把它初始化为一个对象
【问题讨论】:
-
函数结束时
list_init中的本地struct list list消失了(它是一个局部变量!)。然后存储在数组中的指针悬空。旨在保留函数返回的数据必须是全局的(或函数静态的)或动态分配的(典型情况,然后打开所有权的蠕虫罐)。解决这个问题的一种方法是在 main 中定义lists不是指针列表,而是对象列表。您仍然可以在单独的函数中初始化它们(如果您对通过struct list lists[len] = {};进行的值初始化不满意)。 -
顺便说一句,我建议对类型和变量使用不同的名称。是的,结构标记存在于与 C 中的其他标识符分开的命名空间中,但它仍然不利于可理解性。我也不确定当您将代码移植到 C++ 并希望在新代码中省略冗余关键字
struct时会发生什么(过渡到 C++ 始终是未来的可能性,不应轻易浪费)。 -
@Peter-ReinstateMonica 这很有意义。可以肯定的是,这是否意味着我可以通过两种方式来实现它?我可以将
lists设为struct list的数组并使用struct list list;或struct list指针的数组和malloc函数中的内存来初始化元素。 (另外,你对变量/类型命名是正确的。当我校对我的问题时,我有点羞愧;-)) -
是的,正确的。如果你有一个列表数组,你可以直接写入数组元素的成员,不再需要本地结构。