问题描述
我是 C 新手,还不能在我的程序内存中自由导航。无论如何,我正在创建一个静态内存数据类型 (gc_menu
),它应该保存一个指向在执行时创建的结构 (mcl_items
) 的指针。
为简单起见,mcl_items
结构有一个虚拟方法 (push
),它将在 gc_menu_add_item
内运行并分配给 gc_menu
静态空间。 push
将菜单项名称(字母)和方法保存到 mcl_item
虚拟对象。
mcl_items.h
代码:
[...]
typedef struct Items_t {
int8_t size;
char names[64];
void (*methods[64])();
// Interface
void (*push)(struct Items_t *self,char c,void (*method)());
}mcl_items;
mcl_items *new_mcl_items();
void mcl_items_push(mcl_items *self,void (*method)());
mcl_items.c
代码:
[...]
#include "mcl_items.h"
mcl_items *new_mcl_items() {
fprintf(stderr,"MCL_Items: Generating a new set of mcl_items..");
// Build a virtual object
mcl_items *items = calloc(1,sizeof(struct Items_t));
items->push = mcl_items_push;
// Set data
items->size = 0;
return items;
}
void mcl_items_push(mcl_items *self,void (*method)()) {
fprintf(stderr,"MCL_Items: pushing a new item..");
self->names[self->size] = c;
self->methods[self->size] = method;
self->size ++;
}
gc_menu.h
代码:
#include "items.h"
typedef struct {
// Interface
void (*add_item)(char c,void (*method)());
// Data
mcl_items *items;
}__gc_menu;
extern __gc_menu const gc_menu;
gc_menu.c
代码:
static void gc_menu_add_item(char c,void (*method)) {
fprintf(stderr,"GC_Menu: Passing an new item..");
fprintf(stderr,"length = %i\n",gc_menu.items->size);
gc_menu.items->push(gc_menu.items,c,method);
}
__gc_menu const gc_menu = {gc_menu_add_item,// Virtual methods
new_mcl_items}; // Data
调用 gc_menu.add_item
后发生分段错误,gc_menu.items->size
等于 72,而不是 new_mcl_items
定义中定义的 0。
main.c
代码:
gc_menu.add_item('q',xw->end(xw));
GC_Menu: Passing an new item..length = 72
[1] 66021 segmentation fault (core dumped) ./3D_scean
那我做错了什么?为什么会有如此奇怪的数据写入我的 gc_menu.items
实例?
解决方法
您已将 gc_menu.items
初始化为 new_mcl_items
,即指向函数 new_mcl_items
的指针(它应该给您一个警告,因为它的类型是 mcl_items *(*)(void)
而不是 { {1}})。
看起来您想要的是实际调用函数 mcl_items *
并将 new_mcl_items()
设置为 gc_menu.items
返回的值。你不能用初始化器来做到这一点;在编译或链接时必须知道全局或 new_mcl_items()
对象的初始值设定项。标准 C 没有“构造函数”。
因此您必须从 static
的声明和定义中删除 const
,并将代码添加到 gc_menu
(或由 main
调用的某些函数等) 在运行时初始化 main
。
gc_menu.items
:
gc_menu.h
extern __gc_menu gc_menu;
:
gc_menu.c
__gc_menu gc_menu = {
gc_menu_add_item,NULL // or whatever else you like
};
或您所称的任何名称:
main.c