【发布时间】:2019-09-13 13:40:17
【问题描述】:
您好,TIA 为您提供帮助。由于我不熟悉发布问题,因此我欢迎任何有关如何提出此问题的反馈。我在 SO 中进行了很多研究,但没有找到我认为我在寻找的东西。
我还在努力,我不太擅长 C。
我的目的是从给定 XML 的某些特定标签中提取数据并将其写入文件。我的问题出现了,因为当我尝试填充为此目的创建的数据结构时,realloc() 函数在某个时刻给了我一个指向超出范围的地址的指针。
如果你看这个例子
#include <stdio.h>
int main() {
char **arrayString = NULL;
char *testString;
testString = malloc(sizeof("1234567890123456789012345678901234567890123456789"));
strcpy(testString, "1234567890123456789012345678901234567890123456789");
int numElem = 0;
while (numElem < 50) {
numElem++;
arrayString = realloc(arrayString, numElem * sizeof(char**));
arrayString[numElem-1] = malloc(strlen(testString)+1);
strcpy(arrayString[numElem-1], testString);
}
printf("done\n");
return 0;
}
它对我的代码做了类似但简化的事情。基本上尝试用 c 字符串填充 char** 但它会出现段错误。 (是的,我知道我使用的是 strcpy 而不是它更安全的替代方案,但据我所知,它会复制到 '\0',当你在“”之间写一个字符串时,它会自动包含在内,这就是我所需要的)
下面我会详细解释。
在这段代码中,我使用了 libxml2,但你不需要知道它来帮助我。
我有一个这样声明的自定义结构:
struct List {
char key[24][15];
char **value[15];
int size[15];
};
struct List *list; //i've tried to make this static after reading that it could make a difference but to no avail
其中填充了必要的键值。 list->size[] 用零初始化,以跟踪我在 value 中插入了多少值。
value 是这样定义的,因为对于每个键,我需要一个 char* 数组来存储与其关联的每个值。 (我已经考虑过了,但这可能是一种错误的方法,欢迎提出建议 - 但这不是问题的目的)
我遍历 xml 文件,并且对于每个节点,我在节点名称和我的每个键之间执行 strcmp。当存在匹配时,该键的索引将用作value 矩阵中的索引。然后我尝试为 c 字符串矩阵扩展分配的内存,然后为单个 char* 扩展分配的内存。
“损坏”的代码,如下,其中
-
read是上述key的索引。 -
reader是 xmlNode -
string包含 xmlNode 的名称,但随后被释放,因此将其视为新 char* -
list就是上面声明的结构体
if (xmlTextReaderNodeType(reader) == 3 && read >= 0)
{
/* pull out the node value */
xmlChar *value;
value = xmlTextReaderValue(reader);
if (value != NULL) {
free(string);
string=strdup(value);
/*increment array size */
list->size[read]++;
/* allocate char** */ list->value[read]=realloc(list->value[read],list->size[read] * sizeof(char**));
if (list->value[read] == NULL)
return 16;
/*allocate string (char*) memory */
list->value[read][list->size[read]-1] = realloc(list->value[read][list->size[read]-1], sizeof(char*)*sizeof(string));
if (list->value[read][list->size[read]-1] == NULL)
return 16;
/*write string in list */
strcpy(list->value[read][list->size[read]-1], string);
}
/*free memory*/
xmlFree(value);
}
xmlFree(name);
free(string);
我希望这会分配 char**,然后是 char*,但是在这段代码的几次迭代之后(这是一个包装在 while 循环中的函数),我得到了一个段错误。
用 gdb 分析这个(不是专家,只是在运行中学习它)我注意到确实代码似乎在 15 次迭代中按预期工作。在第 16 次迭代中,list->value[read][list->size[read]-1] 大小增加后,list->value[read][list->size[read]-1] 指向一个 0x51,标记为地址越界。 realloc 仅将其带到 0x3730006c6d782e31,仍标记为越界。我希望它指向最后分配的值。
这是一张图片:https://imgur.com/a/FAHoidp
如何正确分配所需的内存而不会超出范围?
【问题讨论】:
-
char *testString没有分配存储空间,而您strcpy! -
这个问题非常需要minimal reproducible example。你所有的sn-ps都有一些问题,不清楚要解决哪一个。
-
sizeof(testString)将是指针的大小,使用strlen -
你说得对。让我修正那个例子。虽然我不需要修复它:-)
-
@AndrewHenle 如果他只打电话给
sizeof(),它会为\0留出空间...