我正在尝试从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。