"realloc(): invalid next size" 当重新分配一个作为结构成员的 char** 指针的内存时
"realloc(): invalid next size" when reallocating memory a char** pointer that is a member of a struct
我最近才开始学习 C,在计算内存分配时遇到了问题。我花了大约最后 2 到 3 天的额外时间试图解决这个问题,但还没有找到解决方案。所以首先,我有两个结构:
struct _list {
// arr is an array of string arrays
char **arr;
// recs tracks how many records are in the list
size_t recs;
// arrSizes records the size of each string array in arr
size_t *arrSizes;
};
typedef struct _list list_t;
和
struct _string {
char *string;
// size is used to store strlen
size_t size;
};
typedef struct _string string_t;
我将以上结构分别初始化为以下几种方式
list_t:
list_t *NewList() {
list_t *List = NULL;
List = malloc(sizeof(*List));
if (List == NULL) {
fprintf(stderr, "Failed to allocate memory to list structure.\n");
return NULL;
}
List->arr = malloc(sizeof(List->arr));
if (List->arr == NULL) {
free(List);
fprintf(stderr, "Failed to allocate memory to list array.\n");
return NULL;
}
List->arrSizes = malloc(sizeof(List->arrSizes));
if (List->arr == NULL) {
free(List);
fprintf(stderr, "Failed to allocate memory to size array.\n");
return NULL;
}
List->recs = 0;
return List;
}
string_t:
// a string array read in by the program is passed with "char* record"
string_t *NewString(char *record)
{
string_t *String = NULL;
String = malloc(sizeof * String);
if (String == NULL) {
fprintf(stderr, "Failed to allocate memory to string structure.\n");
return NULL;
}
String->size = strlen(record) + 1;
String->string = malloc(String->size);
if (String->string == NULL) {
free(String);
fprintf(stderr, "Failed to allocate memory to string array.\n");
return NULL;
}
strcpy(String->string, record);
return String;
}
我从文件中读取行并使用类似于以下代码的内容将它们加载到“匹配结果”缓冲区中。请忽略退出和结构初始化完成后我没有空处理的事实;稍后我会添加一些更有用的东西。另外,对长度感到抱歉。我进行了相当多的编辑,以生成我能想到的重现问题的最小示例。
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
// Check if File exists
void FileExists(FILE *FilePath) {
if (FilePath == NULL) {
fprintf(stderr, "Error: File not found.\n");
exit(1);
}
}
// Delete a string_t struct
int delString(string_t *Structure)
{
if (Structure != NULL) {
free(Structure->string);
free(Structure);
return 0;
}
return 1;
}
// Allocate memory for additional elements added to members of list_t struct
void AllocList(list_t *List, size_t StrLen)
{
char **ArrStrArr_tmp;
size_t *SizeArr_tmp;
char *StrArr_tmp;
ArrStrArr_tmp = realloc(*List->arr, sizeof(**ArrStrArr_tmp) * List->recs);
SizeArr_tmp = realloc(List->arrSizes, sizeof(*SizeArr_tmp) * List->recs);
StrArr_tmp = malloc(sizeof(*StrArr_tmp) * StrLen);
if ((ArrStrArr_tmp == NULL) || (SizeArr_tmp == NULL)
|| (StrArr_tmp == NULL)) {
fprintf(stderr, "Failed to allocate memory.\n");
exit(1);
}
else {
List->arr = ArrStrArr_tmp;
List->arrSizes = SizeArr_tmp;
(List->arr)[List->recs-1]= StrArr_tmp;
}
}
// Add a record to a buffer
int AddRecord(list_t *List, char *AppendRecord)
{
string_t *line = NewString(AppendRecord);
List->recs++;
AllocList(List, line->size);
(List->arr)[List->recs - 1] = line->string;
(List->arrSizes)[List->recs - 1] = line->size;
delString(line);
return 0;
}
// Sends entire string array to lowercase
void tolowerString(char *UpperString, size_t StrLen)
{
int i;
for (i = 0; i < (int)StrLen; i++) {
UpperString[i] = (char)tolower(UpperString[i]);
}
}
// Attempt to match string in lines from a file; lines with matches are read into a buffer
int main()
{
char line[80];
int PrintedLines = 0;
list_t *ResultList = NewList();
char *MyString = "theme";
char *Filename = "List.txt";
FILE *in = fopen(Filename, "r");
// Check if file exists
FileExists(in);
while (fscanf(in, "%79[^\n]\n", line) == 1)
{
char LookString[80];
strcpy(LookString, line);
LookString[strlen(LookString) - 1] = '[=15=]';
// send lookstring to lowercase
tolowerString(LookString, strlen(LookString));
// add line to buffer ResultList if it contains MyString
if (strstr(LookString, MyString)) {
AddRecord(ResultList, line);
PrintedLines++;
}
}
// If PrintedLines is at zero after the while statement terminates, return in abnormal state
if (PrintedLines == 0) {
fprintf(stderr, "No matches found. Please check your input if you are sure there is a match.\n");
return 1;
}
fclose(in);
return 0;
}
当试图将第 5 条匹配记录读入我的缓冲区时,我的程序在 AllocList 函数的这一行崩溃:
ArrStrArr_tmp = realloc(*List->arr, sizeof(**ArrStrArr_tmp) * List->recs);
我在上面 post 编辑的版本中收到以下消息:
realloc(): invalid old size
aborted (core dumped)
我的猜测是,在使用初始 malloc 中的一些默认内存量后,我 运行 陷入了错误,但我不知道究竟是什么导致了这种情况。在我的实际代码中,我正在打印各种东西(指针大小等),但我仍然无法发现任何东西。奇怪的是,在写这个post之前,我居然看到了错误:
realloc(): invalid next size
aborted (core dumped)
但由于某些原因我现在无法重现...
我还读到,每当我将一个元素添加到其中一个成员时,我应该为我的 list_t 结构重新分配内存,但重新分配它实际上不会改变这个程序崩溃的位置或方式。无论如何,我不确定我应该如何为我的结构重新分配内存。澄清一下,我的问题是:
- 是什么导致了这个内存问题?
- 我应该为我的列表结构重新分配内存吗?考虑到我要向 arr 和 arrSizes 成员添加额外的元素,我应该重新分配多少内存?
如崩溃所示,行
ArrStrArr_tmp = realloc(*List->arr, sizeof(**ArrStrArr_tmp) * List->recs);
错了。
这让它读取通过 malloc()
分配的未初始化缓冲区,其值是不确定的。
这行的意思是重新分配List->arr
指向的数组,是char*
.
的数组
因此,该行应该是
ArrStrArr_tmp = realloc(List->arr, sizeof(*ArrStrArr_tmp) * List->recs);
就像下面这行,重新分配一个size_t
.
的数组
SizeArr_tmp = realloc(List->arrSizes, sizeof(*SizeArr_tmp) * List->recs);
另外我发现还有2点需要改进:
首先,函数NewList
中的一些malloc()
用法不好。
该函数正在创建零元素数组,因此 List->arr
和 List->arrSizes
不需要 space。
另请注意,realloc()
接受 NULL
作为要重新分配的缓冲区。
list_t *NewList() {
list_t *List = NULL;
List = malloc(sizeof(*List));
if (List == NULL) {
fprintf(stderr, "Failed to allocate memory to list structure.\n");
return NULL;
}
List->arr = NULL;
List->arrSizes = NULL;
List->recs = 0;
return List;
}
其次,您在 AddRecord
中复制指针而不是字符串,
所以你有内存泄漏和潜在的释放后使用的问题。
似乎应该复制字符串:
(List->arr)[List->recs - 1] = line->string;
应该是
strcpy((List->arr)[List->recs - 1], line->string);
我最近才开始学习 C,在计算内存分配时遇到了问题。我花了大约最后 2 到 3 天的额外时间试图解决这个问题,但还没有找到解决方案。所以首先,我有两个结构:
struct _list {
// arr is an array of string arrays
char **arr;
// recs tracks how many records are in the list
size_t recs;
// arrSizes records the size of each string array in arr
size_t *arrSizes;
};
typedef struct _list list_t;
和
struct _string {
char *string;
// size is used to store strlen
size_t size;
};
typedef struct _string string_t;
我将以上结构分别初始化为以下几种方式
list_t:
list_t *NewList() {
list_t *List = NULL;
List = malloc(sizeof(*List));
if (List == NULL) {
fprintf(stderr, "Failed to allocate memory to list structure.\n");
return NULL;
}
List->arr = malloc(sizeof(List->arr));
if (List->arr == NULL) {
free(List);
fprintf(stderr, "Failed to allocate memory to list array.\n");
return NULL;
}
List->arrSizes = malloc(sizeof(List->arrSizes));
if (List->arr == NULL) {
free(List);
fprintf(stderr, "Failed to allocate memory to size array.\n");
return NULL;
}
List->recs = 0;
return List;
}
string_t:
// a string array read in by the program is passed with "char* record"
string_t *NewString(char *record)
{
string_t *String = NULL;
String = malloc(sizeof * String);
if (String == NULL) {
fprintf(stderr, "Failed to allocate memory to string structure.\n");
return NULL;
}
String->size = strlen(record) + 1;
String->string = malloc(String->size);
if (String->string == NULL) {
free(String);
fprintf(stderr, "Failed to allocate memory to string array.\n");
return NULL;
}
strcpy(String->string, record);
return String;
}
我从文件中读取行并使用类似于以下代码的内容将它们加载到“匹配结果”缓冲区中。请忽略退出和结构初始化完成后我没有空处理的事实;稍后我会添加一些更有用的东西。另外,对长度感到抱歉。我进行了相当多的编辑,以生成我能想到的重现问题的最小示例。
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
// Check if File exists
void FileExists(FILE *FilePath) {
if (FilePath == NULL) {
fprintf(stderr, "Error: File not found.\n");
exit(1);
}
}
// Delete a string_t struct
int delString(string_t *Structure)
{
if (Structure != NULL) {
free(Structure->string);
free(Structure);
return 0;
}
return 1;
}
// Allocate memory for additional elements added to members of list_t struct
void AllocList(list_t *List, size_t StrLen)
{
char **ArrStrArr_tmp;
size_t *SizeArr_tmp;
char *StrArr_tmp;
ArrStrArr_tmp = realloc(*List->arr, sizeof(**ArrStrArr_tmp) * List->recs);
SizeArr_tmp = realloc(List->arrSizes, sizeof(*SizeArr_tmp) * List->recs);
StrArr_tmp = malloc(sizeof(*StrArr_tmp) * StrLen);
if ((ArrStrArr_tmp == NULL) || (SizeArr_tmp == NULL)
|| (StrArr_tmp == NULL)) {
fprintf(stderr, "Failed to allocate memory.\n");
exit(1);
}
else {
List->arr = ArrStrArr_tmp;
List->arrSizes = SizeArr_tmp;
(List->arr)[List->recs-1]= StrArr_tmp;
}
}
// Add a record to a buffer
int AddRecord(list_t *List, char *AppendRecord)
{
string_t *line = NewString(AppendRecord);
List->recs++;
AllocList(List, line->size);
(List->arr)[List->recs - 1] = line->string;
(List->arrSizes)[List->recs - 1] = line->size;
delString(line);
return 0;
}
// Sends entire string array to lowercase
void tolowerString(char *UpperString, size_t StrLen)
{
int i;
for (i = 0; i < (int)StrLen; i++) {
UpperString[i] = (char)tolower(UpperString[i]);
}
}
// Attempt to match string in lines from a file; lines with matches are read into a buffer
int main()
{
char line[80];
int PrintedLines = 0;
list_t *ResultList = NewList();
char *MyString = "theme";
char *Filename = "List.txt";
FILE *in = fopen(Filename, "r");
// Check if file exists
FileExists(in);
while (fscanf(in, "%79[^\n]\n", line) == 1)
{
char LookString[80];
strcpy(LookString, line);
LookString[strlen(LookString) - 1] = '[=15=]';
// send lookstring to lowercase
tolowerString(LookString, strlen(LookString));
// add line to buffer ResultList if it contains MyString
if (strstr(LookString, MyString)) {
AddRecord(ResultList, line);
PrintedLines++;
}
}
// If PrintedLines is at zero after the while statement terminates, return in abnormal state
if (PrintedLines == 0) {
fprintf(stderr, "No matches found. Please check your input if you are sure there is a match.\n");
return 1;
}
fclose(in);
return 0;
}
当试图将第 5 条匹配记录读入我的缓冲区时,我的程序在 AllocList 函数的这一行崩溃:
ArrStrArr_tmp = realloc(*List->arr, sizeof(**ArrStrArr_tmp) * List->recs);
我在上面 post 编辑的版本中收到以下消息:
realloc(): invalid old size
aborted (core dumped)
我的猜测是,在使用初始 malloc 中的一些默认内存量后,我 运行 陷入了错误,但我不知道究竟是什么导致了这种情况。在我的实际代码中,我正在打印各种东西(指针大小等),但我仍然无法发现任何东西。奇怪的是,在写这个post之前,我居然看到了错误:
realloc(): invalid next size
aborted (core dumped)
但由于某些原因我现在无法重现...
我还读到,每当我将一个元素添加到其中一个成员时,我应该为我的 list_t 结构重新分配内存,但重新分配它实际上不会改变这个程序崩溃的位置或方式。无论如何,我不确定我应该如何为我的结构重新分配内存。澄清一下,我的问题是:
- 是什么导致了这个内存问题?
- 我应该为我的列表结构重新分配内存吗?考虑到我要向 arr 和 arrSizes 成员添加额外的元素,我应该重新分配多少内存?
如崩溃所示,行
ArrStrArr_tmp = realloc(*List->arr, sizeof(**ArrStrArr_tmp) * List->recs);
错了。
这让它读取通过 malloc()
分配的未初始化缓冲区,其值是不确定的。
这行的意思是重新分配List->arr
指向的数组,是char*
.
因此,该行应该是
ArrStrArr_tmp = realloc(List->arr, sizeof(*ArrStrArr_tmp) * List->recs);
就像下面这行,重新分配一个size_t
.
SizeArr_tmp = realloc(List->arrSizes, sizeof(*SizeArr_tmp) * List->recs);
另外我发现还有2点需要改进:
首先,函数NewList
中的一些malloc()
用法不好。
该函数正在创建零元素数组,因此 List->arr
和 List->arrSizes
不需要 space。
另请注意,realloc()
接受 NULL
作为要重新分配的缓冲区。
list_t *NewList() {
list_t *List = NULL;
List = malloc(sizeof(*List));
if (List == NULL) {
fprintf(stderr, "Failed to allocate memory to list structure.\n");
return NULL;
}
List->arr = NULL;
List->arrSizes = NULL;
List->recs = 0;
return List;
}
其次,您在 AddRecord
中复制指针而不是字符串,
所以你有内存泄漏和潜在的释放后使用的问题。
似乎应该复制字符串:
(List->arr)[List->recs - 1] = line->string;
应该是
strcpy((List->arr)[List->recs - 1], line->string);