c - 动态分配包含动态分配数组的结构数组
问题描述
我正在尝试从 XML 文件中读取设置值并让事情变得更简单,我设置了一个包含每个值的结构。其中之一是结构数组。然后我将结构初始化为一个数组。
在运行代码时,我有时会顺利运行,有时会出现段错误,有时会出现中止陷阱 ( malloc: *** error for object: incorrect checksum for freed object - object was probably modified after being freed. *** set a breakpoint in malloc_error_break to debug Abort trap: 6
)。我想这是未定义的行为。
我可能对为什么会发生这种情况有所暗示,但我无法得到任何确认,尽管我做了大量的研究。
在我看来,这是由于结构数组的空间分配分配了足够的内存来包含具有一些值的结构加上一个空的结构数组。然后我为第二个结构数组分配内存,因此改变了第一个结构数组所需的空间。
这些是结构的声明:
struct Delegate {
int warnings;
gchar *name;
};
struct Staff {
gchar *president;
gchar *vice;
gchar *mod;
};
struct Committee {
int n_delegate;
gchar *name;
gchar *topics[2];
struct Delegate *delegates;
struct Staff staff;
};
这是我要运行的代码:
static void load_prop() {
xmlDocPtr doc;
xmlNodePtr node;
xmlNodePtr subnode;
xmlNodePtr subsubnode;
xmlNodePtr subsubsubnode;
xmlChar *cnumber;
doc = xmlParseFile("/Users/username/Documents/Obermun/DebateProgram/res/xml/property.xml");
node = xmlDocGetRootElement(doc);
edition = (char *) xmlGetProp(node, (const xmlChar *) "edition");
int const index = atoi((const char*)(xmlGetProp(node, (const xmlChar *) "committees")));
committees = (Committee *) malloc(sizeof(Committee)*index);
subnode = node -> xmlChildrenNode;
int i = 0;
int t = 0;
int d = 0;
while(subnode != NULL) {
if(!xmlStrcmp(subnode -> name, (const xmlChar *) "committee")) {
committees[i].name = (char *) xmlGetProp(subnode, (const xmlChar *) "name");
committees[i].n_delegate = atoi((const char*) xmlGetProp(subnode, (const xmlChar *) "delegates"));
committees[i].delegates = (Delegate *) malloc(sizeof(Delegate)*committees[i].n_delegate);
subsubnode = subnode -> xmlChildrenNode;
while(subsubnode != NULL) {
if(!xmlStrcmp(subsubnode -> name, (const xmlChar *) "topic")) {
committees[i].topics[t] = (char *) xmlNodeListGetString(doc, subsubnode -> xmlChildrenNode, 1);
t++;
}
else if(!xmlStrcmp(subsubnode -> name, (const xmlChar *) "delegate")) {
committees[i].delegates[d].warnings = atoi((const char*) xmlGetProp(subsubnode, (const xmlChar *) "warnings"));
committees[i].delegates[d].name = (char *) xmlNodeListGetString(doc, subsubnode -> xmlChildrenNode, 1);
d++;
}
else if(!xmlStrcmp(subsubnode -> name, (const xmlChar *) "staff")) {
subsubsubnode = subsubnode -> xmlChildrenNode;
while(subsubsubnode != NULL) {
if(!xmlStrcmp(subsubnode -> name, (const xmlChar *) "president")) {
committees[i].staff.president = (char *) xmlNodeListGetString(doc, subsubsubnode -> xmlChildrenNode, 1);
}
if(!xmlStrcmp(subsubnode -> name, (const xmlChar *) "vice")) {
committees[i].staff.vice = (char *) xmlNodeListGetString(doc, subsubsubnode -> xmlChildrenNode, 1);
}
if(!xmlStrcmp(subsubnode -> name, (const xmlChar *) "mod")) {
committees[i].staff.mod = (char *) xmlNodeListGetString(doc, subsubsubnode -> xmlChildrenNode, 1);
}
subsubsubnode = subsubsubnode -> next;
}
}
subsubnode = subsubnode -> next;
}
i++;
}
subnode = subnode -> next;
}
}
尝试用gdb
我得到这个回溯来调试代码:
Thread 2 received signal SIGABRT, Aborted.
0x00007fff7353ab66 in ?? () from /usr/lib/system/libsystem_kernel.dylib
(gdb) bt
#0 0x00007fff7353ab66 in ?? () from /usr/lib/system/libsystem_kernel.dylib
#1 0x00007fff73705080 in pthread_kill () from /usr/lib/system/libsystem_pthread.dylib
#2 0x00007fff734961ae in abort () from /usr/lib/system/libsystem_c.dylib
#3 0x0000003000000010 in ?? ()
#4 0x00007ffeffffffdf in ?? ()
#5 0xffffffff0160f658 in ?? ()
#6 0x000000010160f658 in ?? ()
#7 0x00007ffeefbff5f0 in ?? ()
#8 0x00007fff7359fb58 in szone_error () from /usr/lib/system/libsystem_malloc.dylib
Backtrace stopped: frame did not save the PC
解决方案
正如@nwellnhof 在评论中指出的那样,这个代码片段的问题是我用来存储委托和主题值的变量d
永远t
不会重置为 0,所以它们每个周期都在增长,试图将值存储在非分配的内存空间,导致未定义的行为。
正确的代码如下:
static void load_prop() {
xmlDocPtr doc;
xmlNodePtr node;
xmlNodePtr subnode;
xmlNodePtr subsubnode;
xmlNodePtr subsubsubnode;
xmlChar *cnumber;
doc = xmlParseFile("/Users/username/Documents/Obermun/DebateProgram/res/xml/property.xml");
node = xmlDocGetRootElement(doc);
edition = (char *) xmlGetProp(node, (const xmlChar *) "edition");
int const index = atoi((const char*)(xmlGetProp(node, (const xmlChar *) "committees")));
committees = (struct Committee *) malloc(sizeof(struct Committee)*index);
subnode = node -> xmlChildrenNode;
int i = 0;
int t = 0;
int d = 0;
while(subnode != NULL) {
if(!xmlStrcmp(subnode -> name, (const xmlChar *) "committee")) {
committees[i].name = strdup((char *) xmlGetProp(subnode, (const xmlChar *) "name"));
committees[i].n_delegate = atoi((const char*) xmlGetProp(subnode, (const xmlChar *) "delegates"));
committees[i].delegates = (struct Delegate *) malloc(sizeof(struct Delegate)*committees[i].n_delegate);
subsubnode = subnode -> xmlChildrenNode;
t = 0;
d = 0;
while(subsubnode != NULL) {
if(!xmlStrcmp(subsubnode -> name, (const xmlChar *) "topic")) {
committees[i].topics[t] = strdup((char *) xmlNodeListGetString(doc, subsubnode -> xmlChildrenNode, 1));
t++;
}
else if(!xmlStrcmp(subsubnode -> name, (const xmlChar *) "delegate")) {
committees[i].delegates[d].warnings = atoi((const char*) xmlGetProp(subsubnode, (const xmlChar *) "warnings"));
committees[i].delegates[d].name = strdup((char *) xmlNodeListGetString(doc, subsubnode -> xmlChildrenNode, 1));
d++;
}
else if(!xmlStrcmp(subsubnode -> name, (const xmlChar *) "staff")) {
subsubsubnode = subsubnode -> xmlChildrenNode;
while(subsubsubnode != NULL) {
if(!xmlStrcmp(subsubnode -> name, (const xmlChar *) "president")) {
committees[i].staff.president = strdup((char *) xmlNodeListGetString(doc, subsubsubnode -> xmlChildrenNode, 1));
}
if(!xmlStrcmp(subsubnode -> name, (const xmlChar *) "vice")) {
committees[i].staff.vice = strdup((char *) xmlNodeListGetString(doc, subsubsubnode -> xmlChildrenNode, 1));
}
if(!xmlStrcmp(subsubnode -> name, (const xmlChar *) "mod")) {
committees[i].staff.mod = strdup((char *) xmlNodeListGetString(doc, subsubsubnode -> xmlChildrenNode, 1));
}
subsubsubnode = subsubsubnode -> next;
}
}
subsubnode = subsubnode -> next;
}
i++;
}
subnode = subnode -> next;
}
}
注意t
并d
在每个周期之前设置为 0。
推荐阅读
- android-studio - com.android.support:appcompat-v7:27.1.1 与 media-compat:25.2.0 不匹配
- python-3.x - 减少火花返回字典而不是数据帧中的操作
- git - 合并来自拉取请求的单个提交
- python - Python 子类的 Pythonic 方式
- python - 使用 Python Zeep 内省 WSDL
- php - 当我尝试将查询(插入)插入到 if 条件时,然后双插入?
- r - nleqslv, R, 非线性方程组
- node.js - Firebase 工具安装经常卡住
- java - springTemplateEngine 中的转义引号
- youtube - YouTube:获取稍后观看项目的数量