我有一个静态struct数组,其中包含从lua文件解析的数据。
我以为我做得很对,但是当我去加载另一个lua文件时,静态数组就开始打印垃圾了。我不确定加载lua文件后幕后会发生什么,但我无法以其他方式重现它。
这是我的代码和我正在加载的lua文件。
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAX_FILES 5
#define MAX_BOXES 25
struct Box
{
const char *name;
int count;
const char *files[MAX_FILES];
};
static struct Box boxes[MAX_BOXES];
static int box_index = 0;
void script_bail (lua_State * S, const char *fmt, ...)
{
va_list argp;
va_start(argp, fmt);
vfprintf(stderr, fmt, argp);
va_end(argp);
lua_close(S);
exit(EXIT_FAILURE);
}
int box_create (const char* name, int count, const char **files)
{
if (box_index + 1 >= MAX_BOXES)
return 1;
boxes[box_index].name = name;
boxes[box_index].count = count;
memcpy(boxes[box_index].files, files, count * sizeof(char*));
box_index++;
return 0;
}
void load_boxes (lua_State* S)
{
const char * name;
const char * files[MAX_FILES];
int element_index = 1;
int file_index = 0;
lua_getglobal(S, "boxes");
if (!lua_istable(S, -1))
script_bail (S, "'%s' is not a table\n", "boxes");
/* each element has no key */
lua_pushnil(S);
/* iterate through this table of tables */
while (lua_next(S, -2)) {
if (!lua_istable(S, -1))
script_bail (S,
"Element %d of table `classes' is not a table!\n",
element_index);
/* find variable by name `name' and make sure it's a string */
lua_pushstring(S, "name");
lua_gettable(S, -2);
if (!lua_isstring(S, -1))
script_bail (S, "invalid field in table for key: %s", "name");
name = lua_tostring(S, -1);
lua_pop(S, 1);
/* get the table where that's named `components' */
lua_pushstring(S, "files");
lua_gettable(S, -2);
if (!lua_istable(S, -1))
script_bail (S,
"files of element %d is not a table!\n",
element_index);
/* each component has no key */
lua_pushnil(S);
/* go through each component */
while (lua_next(S, -2)) {
if (!lua_isstring(S, -1))
script_bail (S,
"Element %d of files of box %d is not a string!\n",
file_index, element_index);
/* add the component file to our index and increment the index */
files[file_index++] = lua_tostring(S, -1);
/* pop current to move to next */
lua_pop(S, 1);
}
if (box_create(name, file_index, files) != 0)
script_bail(S, "boxes exceeds limit of %d\n", MAX_BOXES);
/* pop the files table */
/* pop the current table to make room for the next */
lua_pop(S, 2);
element_index++;
file_index = 0;
}
lua_pop(S, 1);
}
lua_State * load_lua_file (const char *filename)
{
lua_State * S = luaL_newstate();
luaL_openlibs(S);
if (luaL_loadfile(S, filename) || lua_pcall(S, 0, 0, 0))
script_bail (S, "Can't load %s into memory\n", filename);
return S;
}
void print_boxes()
{
struct Box *box;
printf("index: %d\n", box_index);
int i, j;
for (i = 0; i < box_index; i++) {
box = &boxes[i];
printf("%p: %s => {", box, box->name);
for (j = 0; j < box->count; j++) {
printf(" %s ", box->files[j]);
}
printf("}\n");
}
}
int main (void)
{
lua_State * S = load_lua_file ("boxes.lua");
load_boxes(S);
lua_close(S);
print_boxes();
lua_State * N = load_lua_file ("boxes.lua");
lua_close(N);
print_boxes();
return 0;
}
boxes = {
{ name = "first", files = { "one.lua" } },
{ name = "second", files = { "two.lua", "three.lua", "four.lua" } }
};
以下是我得到的输出:
0x10f985330: first => { one.lu }
0x10f985368: second => { two.lu three.lua four.lua }
0x10f985330: second => { D }
0x10f985368: D => { J????? ?
(? }
我想要注意到这种情况偶尔会发生。有时它会打印两次相同的数据(暗示它正在工作)。大部分时间我得到上述内容。我做错了什么导致数组内存损坏?
答案 0 :(得分:3)
似乎你创建了一个指向某个内存块的指针,这个内存块在某个时候被解除分配,我想这里
lua_close(S);
然后,当您尝试访问结构中的files
或name
时,指针指向垃圾。
您需要复制字符串,您可以使用strdup()
或任何等效函数,保存指针的每个字符串在打印框时仍必须有效。
更好的解决方案是在打印框之前不释放lua库分配的内存,你可以在lua_close(S);
调用后移动print_boxes()
来实现。
因为如果你使用strdup()
,那么你不再需要访问它们就必须在指针上调用free()
,这不会直接起作用,因为poitner符合{{1}的条件},所以如果你使用const
,你需要
strdup()
。const
返回的值的每个指针上调用free()
。