我想知道如何malloc(和hen realloc)一个结构数组。这是我的结构:
typedef struct tag {
char *key;
char *val;
} tag;
我在另一个结构中使用此结构:
typedef struct node {
int id;
double lat;
double lon;
int visible;
tag *tab;
} node;
我定义一个node *n
,然后:
n->tab = (tag*)malloc(sizeof(tag) * 5);
但我有一个错误malloc corruption
.
void remplisTag(xmlNodePtr cur, node *n) {
xmlNodePtr fils;
n->tab = malloc(sizeof(*n->tab) * 5);
if (n->tab == NULL) {
error(E_ERROR_MALLOC);
}
printf("apres mallocn");
int taille = 5;
int ind = 0;
xmlAttrPtr attr1, attr2;
xmlChar *key;
xmlChar *value;
fils = cur->xmlChildrenNode;
fils = fils->next;
while (xmlStrcmp(fils->name, (const xmlChar*)"text") != 0) {
if (xmlStrcmp(fils->name, (const xmlChar*)"tag") == 0) {
if (ind == taille - 1) {
n->tab = realloc(n->tab, sizeof(tag) * (taille + 5));
taille = taille + 5;
} else {
taille = taille;
}
/* searching for key */
attr1 = xmlHasProp(fils, (const xmlChar*)"k");
if (attr1 == NULL) {
error(E_KEY);
} else {
key = xmlGetProp(fils, (const xmlChar*)"k");
if (key == NULL) {
error(E_KEY_V);
}
/* searching for value */
attr2 = xmlHasProp(fils, (const xmlChar*)"v");
if (attr2 == NULL) {
error(E_VALUE);
}
value = xmlGetProp(fils, (const xmlChar*)"v");
if (value == NULL) {
error(E_VALUE_V);
}
tag t;
t.key = malloc(sizeof((char*)key));
strcpy(t.key, (char*)key);
strcpy(t.val, (char*)value);
t.val = malloc(sizeof((char*)value));
n->tab[ind++] = t;
}
}
fils = fils->next;
}
free(n->tab);
}
在main
:
node *n = malloc(sizeof(node));
xmlNodePtr cur;
在while
循环中:
remplisTag(cur, n);
以下行中存在内存分配问题
tag t;
t.key = malloc(sizeof((char*)key));
strcpy(t.key, (char*)key);
strcpy(t.val, (char*)value);
t.val = malloc(sizeof((char*)value));
C 语言中的内存非常繁琐 - 当您分配内存时,您需要容纳足够的内存来存储数据。
tag t;
t.key = malloc(sizeof((char*)key));
strcpy(t.key, (char*)key);
为指针创建足够的指针 - 这可能还不够。
修复程序是这样的。
tag t;
t.key = strdup( key );
t.val = strdup( value );
strdup
函数结合了 malloc(大小正确)和 strcpy。
分配语句中没有明显的问题,有些人希望malloc()
返回值不强制转换为目标类型,并且使用目标指针的类型来避免难以检测到的类型不匹配会稍微可靠一些:
n->tab = malloc(sizeof(*n->tab) * 5);
- 您收到的确切错误消息是什么?
- 是运行时错误吗?
- 您是如何分配
n
指向的node
结构的? - 您可以将完整代码发布到产生此失败的函数吗?
来自 malloc()
的运行时消息指示malloc
内部使用的内存分配结构已损坏。这表明问题出在其他地方,可能是malloc()
分配的另一个对象中的缓冲区溢出。 检查自上次调用 malloc()
以来执行的代码。
编辑:
在发布的代码中,存在一些分配错误:
t.key = malloc(sizeof((char*)key));
strcpy(t.key, (char*)key);
strcpy(t.val, (char*)value);
t.val = malloc(sizeof((char*)value));
- 您分配的空间只是指针
char*
的大小,而不是字符串的长度加上最后一个空终止符的 1。如果key
超过 3 或 7 个字节,则根据体系结构,缓冲区溢出。 -
t.val
是在将内容复制到其中后分配的。未定义的行为!
您应该使用以下strdup()
来简化此操作:
t.key = strdup((char*)key);
t.val = strdup((char*)value);
您的重新分配测试过于保守:当ind == taille
时应重新分配数组:
if (ind == taille) {
n->tab = realloc(n->tab, sizeof(*n->tab) * (taille + 5));
taille += 5;
}
taille
和ind
应存储在节点中,以跟踪已分配的空间量和存在的标签数。 当前代码没有向调用方提供此信息,tag
数组的其余部分未初始化,无法分辨,未定义的行为潜伏着。
请注意,代码中的强制转换过多。 强制转换可防止编译器检测某些类型不匹配,明智的做法是更改函数的参数类型以避免不必要的强制转换。
例如:libxml2 将xmlChar
定义为 unsigned char
的 typedef。 这是一个非常糟糕的设计决策。 他们应该使用char
并正确处理字符串,无论char
恰好在当前环境中signed
还是unsigned
。这种选择迫使程序员将大多数参数投射到xmlXXX
API,使代码变得丑陋且容易出错。 您无法更改它,但您可以使用内联函数在 char*
和 xmlChar*
之间进行转换,以将强制转换保持在最低限度。