我是C的新手,还不能自由地浏览我的程序内存。无论如何,我正在创建一个静态内存数据类型(gc_menu
),它应该包含一个指针,指向在执行时创建的结构(mcl_items
)。
为了简单起见,mcl_items
结构有一个虚拟方法(push
),它将在gc_menu_add_item
内部运行,并分配给gc_menu
静态空间。push
保存菜单项名称(字母)和方法到mcl_item
虚拟对象。
mcl_items.h
code:
[...]
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, char c, void (*method)());
mcl_items.c
code:
[...]
#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, char c, 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
code:
#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
code:
static void gc_menu_add_item(char c, void (*method)) {
fprintf(stderr, "GC_Menu: Passing an new item..");
fprintf(stderr, "length = %in", 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
code:
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)
类型而不是mcl_items *
)。
看起来您想要的实际上是调用函数new_mcl_items()
并将gc_menu.items
设置为new_mcl_items()
返回的值。你不能用初始化器这样做;全局或static
对象的初始化式必须在编译或链接时已知。标准C语言没有"构造函数">
因此,您必须从gc_menu
的声明和定义中删除const
,并在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
或者随便你怎么称呼它
int main(void) {
// ...
gc_menu.items = new_mcl_items();
// ...
}