我有一个名为menu_item的结构,如下所示:
struct menu_item
{
char name[ITEM_NAME_LEN+1];
};
在main中我声明了一个指向结构的指针数组(我对这部分是正确的吗?):
struct menu_item * menu_items[NUM_MENU_ITEMS];
主要是我试着打电话:
init_menu(&menu_items[NUM_MENU_ITEMS]);
init_menu函数如下所示:
void menu_init(struct menu_item * menu_items[NUM_MENU_ITEMS])
{
/* allocate memory for each element in the array */
menu_items[NUM_MENU_ITEMS] = (struct menu_item *) malloc(sizeof(struct menu_item));
}
但是我遇到了分段错误,我做错了什么?提前谢谢。
答案 0 :(得分:2)
仔细查看您的功能。
void menu_init(struct menu_item * menu_items[NUM_MENU_ITEMS])
{
/* allocate memory for each element in the array */
menu_items[NUM_MENU_ITEMS] = (struct menu_item *) malloc(sizeof(struct menu_item));
}
您需要在函数的第二个参数中携带数组的大小。但是,NUM_MENU_ITEMS
似乎是全球#define
,因此您不需要携带第二个参数。
然后您正在访问一个出界的单元格menu_items[NUM_MENU_ITEMS]
。我假设您知道索引从0开始并在NUM_MENU_ITEMS-1
结束。
在您的函数中,您需要在循环内部分配内存。而且,你不需要施放malloc返回的东西。
所以,例如,你可以这样做:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ITEM_NAME_LEN 15
#define NUM_MENU_ITEMS 3
// Define the struct before main
struct menu_item {
char name[ITEM_NAME_LEN + 1];
};
// Give a synonym. Now struct menu_item is the same with menu_item_t.
// Notice the _t extension, which implies that this is a typedef.
typedef struct menu_item menu_item_t;
/**
* Given a pointer 'p' to an array of pointers
* (of type menu_item_t), allocate memory for
* every cell of the array.
*/
void init_menu(menu_item_t* p[]) {
int i;
for(i = 0; i < NUM_MENU_ITEMS; ++i) {
// for every cell of our array, allocate memory
p[i] = malloc(sizeof(menu_item_t));
// check that allocation for the i-th cell is OK
if(!p[i]) {
printf("Error in allocating %d item!\n\n", i);
return;
}
}
}
/**
* Given a pointer 'p' to an array of pointers
* (of type menu_item_t), de-allocate memory for
* every cell of the array.
*/
void delete_menu(menu_item_t* p[]) {
int i;
for(i = 0; i < NUM_MENU_ITEMS; ++i) {
// free the memory we had allocated for the i-th cell
free(p[i]);
// set the pointer to NULL
p[i] = NULL;
}
}
void fill(menu_item_t* p[]) {
int i;
for(i = 0; i < NUM_MENU_ITEMS; ++i) {
strcpy(p[i]->name, "myitem");
}
}
void print(menu_item_t* p[]) {
int i;
for(i = 0; i < NUM_MENU_ITEMS; ++i) {
printf("%s\n", p[i]->name);
}
}
int main(void) {
// Declare an array of pointers of menu_items_t.
// The size of the array is NUM_MENU_ITEMS
menu_item_t *menu_items[NUM_MENU_ITEMS];
init_menu(menu_items);
fill(menu_items);
print(menu_items);
delete_menu(menu_items);
return 0;
}
当我处理结构时,我总是记住this示例。
答案 1 :(得分:1)
您正在将您的功能称为
init_menu(&menu_items[NUM_MENU_ITEMS]);
这没有意义。表达式&menu_items[NUM_MENU_ITEMS]
创建指向索引为NUM_MENU_ITEMS
的元素的指针。这种元素不存在。您的数组包含从0
到NUM_MENU_ITEMS - 1
编号的元素。没有索引为NUM_MENU_ITEMS
的元素。
表达式&menu_items[NUM_MENU_ITEMS]
生成一个指向超出数组末尾的未知内存的指针。您将该指针传递给该函数。稍后您尝试使用该指针,就好像它是您的数组一样。你写入了未知的内存,导致崩溃。
如果要将数组传递给函数,只需传递它即可。您的函数应该被称为
init_menu(menu_items);
就是这样。没有必要为任何带有奇怪索引的元素创建任何指针。
稍后,在您的函数内部,您将再次尝试访问数组的元素NUM_MENU_ITEMS
menu_items[NUM_MENU_ITEMS] = ...
由于同样的原因,这没有任何意义。