C结构:初始化的字符串无效
下面的代码示例以两种不同的方式获取指向结构的指针。当第一个(“Test1”)成功时,第二个在尝试输出字符串(标题)时失败,并且正确打印了数字(类型):C结构:初始化的字符串无效,c,struct,C,Struct,下面的代码示例以两种不同的方式获取指向结构的指针。当第一个(“Test1”)成功时,第二个在尝试输出字符串(标题)时失败,并且正确打印了数字(类型): #include <stdio.h> #include <stdlib.h> typedef struct{ unsigned char type; char* title; } MenuItem; typedef struct{ unsigned short itemCount; Me
#include <stdio.h>
#include <stdlib.h>
typedef struct{
unsigned char type;
char* title;
} MenuItem;
typedef struct{
unsigned short itemCount;
MenuItem *items;
} Menu;
Menu* createMenu(unsigned short itemCount, MenuItem items[]){
Menu *menu = malloc(sizeof(Menu));
menu->itemCount = itemCount;
menu->items = items;
return menu;
}
Menu* getSampleMenu(void){
return createMenu(2,(MenuItem[]){
{3,"Foo2"},
{4,"Bar2"}
});
}
void showMenu(const Menu *menu){
for(unsigned short i = 0; i < menu->itemCount; i++)
printf("Item %d: %d/%s\n",i,menu->items[i].type,menu->items[i].title);
}
int main(void){
//Test 1
Menu *menu = createMenu(2,(MenuItem[]){
{1,"Foo"},
{2,"Bar"}
});
showMenu(menu);
//Result: 1/Foo\n 2/Bar
//Test 2
showMenu(getSampleMenu());
//Result: 3/ [segmentation fault]
}
#包括
#包括
类型定义结构{
无符号字符类型;
字符*标题;
}MenuItem;
类型定义结构{
无符号短项计数;
菜单项*项目;
}菜单;
菜单*创建菜单(未签名的短项计数,菜单项[]){
Menu*Menu=malloc(sizeof(Menu));
菜单->项目计数=项目计数;
菜单->项目=项目;
返回菜单;
}
菜单*getSampleMenu(无效){
返回创建菜单(2,(菜单项[]){
{3,“Foo2”},
{4,“Bar2”}
});
}
无效显示菜单(常量菜单*菜单){
对于(无符号短i=0;iitemCount;i++)
printf(“项目%d:%d/%s\n”,i,菜单->项目[i]。类型,菜单->项目[i]。标题);
}
内部主(空){
//测试1
菜单*菜单=创建菜单(2,(菜单项[]){
{1,“Foo”},
{2,“Bar”}
});
显示菜单(菜单);
//结果:1/Foo\n 2/Bar
//测试2
showMenu(getSampleMenu());
//结果:3/[分段错误]
}
你知道可能是什么问题吗?该示例是在Debian上使用GCC4.6.3在C99模式下编译和测试的
提前谢谢 要传递到
createMenu
的数组具有“自动存储持续时间”。一旦getSampleMenu
结束,它就会消失,指向它的任何指针都将无效
(编辑:它实际上可能比这更严重。数组作为一个临时对象,一旦导致其创建的语句结束,它很可能就死了。在这种情况下,这两个语句大致相当,因为该语句是函数中的最后一个语句……但是createSampleMenu
中是否有后续语句试图关闭该菜单,即使它们可能遵循无效指针。)
您需要动态分配(
malloc
)一些内存,并将数组复制到其中。(当然,您还应该有一个destroyMenu
或类似的函数,以便在菜单不再需要时正确释放内存。)传递到createMenu
的数组具有“自动存储持续时间”。一旦getSampleMenu
结束,它就会消失,指向它的任何指针都将无效
(编辑:它实际上可能比这更严重。数组作为一个临时对象,一旦导致其创建的语句结束,它很可能就死了。在这种情况下,这两个语句大致相当,因为该语句是函数中的最后一个语句……但是createSampleMenu
中是否有后续语句试图关闭该菜单,即使它们可能遵循无效指针。)
您需要动态分配(
malloc
)一些内存,并将数组复制到其中。(当然,您还应该有一个destroyMenu
或类似的函数,以便在菜单不再需要时正确释放内存。)本地声明的变量,也称为“”,通常存储在当前函数的堆栈帧上-因此,当您从声明它们的函数返回时,它们将从堆栈中弹出,稍后调用的函数可以对它们进行写入。malloc
在堆上分配一个内存范围,在调用free
,而不考虑代码所在的范围。本地声明的变量,也称为“”,通常存储在当前函数的堆栈帧上-因此,当您从声明它们的函数返回时,它们将从堆栈中弹出,稍后调用的函数可以对它们进行写入。malloc
在堆上分配一个内存范围,在调用free
,而不考虑代码所处的范围。一旦函数getSampleMenu()
返回,指针menu->items
将不再有效,因为“MenuItem[]”是在该函数中本地定义的
因此,在测试2中,当访问
showMenu()
中的menu->items
时,如果函数getSampleMenu()
返回,则指针menu->items
将不再有效,因为“MenuItem[]”是在该函数中本地定义的
因此,在测试2中,当访问showMenu()
中的menu->items
时,程序会发生故障