如何回收和重用分配的内存?
How to recycle and reuse allocated memory?
我现在正在做的是一个基于状态的解析器,用于流中的任何输入。我的教授告诉我这是避免特殊情况的最好方法。我设置它的方法是使用函数,我在尝试重用分配的内存时遇到了一些麻烦,所以我不会造成任何泄漏。我正在解析的是多个参数。每个参数都有一个名称和一个值。输入示例为:
parameterName = 500;
名称为 parameterName,类型为 integer,值为 500 .
我能够在没有内存泄漏的情况下成功解析其中之一。但是,执行第二个参数会导致泄漏,我知道原因:这是 malloc 在我的参数名称上的多次使用。
看一下解析代码:
int main()
{
int x;
char c;
char *nameTemp;
int hasName = 0;
int hasEqual = 0;
/* ParameterManager values */
ParameterManager *pm;
pm = PM_create(500);
if((PM_manage(pm, "name", INT_TYPE, 1)));
while((x = getchar()) != EOF)
{
/* Cast int to char */
c = (char)x;
/* Whitespace state */
if((isspace(c)))
{
c = whitespace();
}
/* Comment state */
if(c == '#')
{
c = comment();
}
/* Name state */
if(((isalnum(c)) && hasEqual == 0 && hasName == 0))
{
nameTemp = name(c);
printf("Name: %s\n", nameTemp);
hasName = 1;
}
/* Equal state */
if(c == '=' && hasName == 1 && hasEqual == 0)
{
hasEqual = 1;
}
/* Value state */
if((isalnum(c)) && hasName == 1 && hasEqual == 1)
{
getValues(c, nameTemp, pm->t_List, pm->m_List);
hasName = 0;
hasEqual = 0;
}
}
free(nameTemp);
if((PM_destroy(pm)) && DEBUG) printf("Success destroying PM.\n");
return 0;
}
行nameTemp = name(c)
,在/* Name state */
下,returns分配了一个字符串。这个字符串稍后被传递来做其他工作。但是,由于这整个解析思路是在循环中,所以会对同一个字符串进行多次mallocs。我只能释放 nameTemp 一次,但该名称上有多个 mallocs。我怎样才能一遍又一遍地重复使用 nameTemp 而不会造成任何泄漏?
这是一段代码(在函数 name()
中),其中分配了 nameTemp:
/* Make sure temp is not NULL before mallocing */
if(temp[0] != '[=12=]')
{
returnName = malloc(sizeof(char)*strlen(temp)+1);
strncpy(returnName, temp, strlen(temp)+1);
temp[0] = '[=12=]';
return returnName;
}
如果有几件事不清楚,我深表歉意。我尽量做到笼统,所以如果您需要更多说明,请告诉我。
malloc()
不跟踪分配的块。您需要找到完成处理您请求的内存的所有位置,然后 free()
它就在那里。
如果我没看错你的代码,那应该是在你的 while
循环主体的末尾。
编辑:调出评论。
尝试使用您已经 free()
的内存块是未定义的行为。
但是,您用来在块上保留句柄的 指针 只是一个常规指针,在将其传递给 free()
后不会过时.事实上,它根本不会移动,因为 free()
会复制它。
因此,在将指针传递给 free()
后,通常会看到该指针设置为 NULL
,以确保不会意外重用现在无法使用的块。
然后您可以像往常一样很好地重用它作为 malloc()
返回的全新块的句柄。
nameTemp = name(c);
导致不可避免的泄漏,当 nameTemp 存储一个指针时,该指针未保存在其他地方,此时也未释放。
有很多选择可以避免这种情况(取决于您想要实现的目标以及您愿意改变代码结构的程度)。
三种可能性(从最少到最多的代码更改量排序):
- 在再次分配之前释放内存(并在程序结束时再次释放它)
free(nameTemp);
nameTemp = name(c);
- 当内存过时时释放内存
/* Value state */
if((isalnum(c)) && hasName == 1 && hasEqual == 1)
{
getValues(c, nameTemp, pm->t_List, pm->m_List);
hasName = 0;
hasEqual = 0;
free(nameTemp);
nameTemp=NULL;
}
- 使用通用缓冲区,在开始时分配足够大的垃圾内存,并在结束时再次释放它。
char* nameTemp;
nameTemp = (char*)malloc(512); //Or any other size, just check that its actually big enough before writing to it, otherwise buffer overflow errors will occur.
// Somwhere in your program
write_name( nameTemp, 512 , c ); // Pass the buffer to be filled by the function, instead of returning a new pointer.
// At the end of your program
free(nameTemp);
nameTemp = NULL; //Prevent access of freed memory.
我现在正在做的是一个基于状态的解析器,用于流中的任何输入。我的教授告诉我这是避免特殊情况的最好方法。我设置它的方法是使用函数,我在尝试重用分配的内存时遇到了一些麻烦,所以我不会造成任何泄漏。我正在解析的是多个参数。每个参数都有一个名称和一个值。输入示例为:
parameterName = 500;
名称为 parameterName,类型为 integer,值为 500 .
我能够在没有内存泄漏的情况下成功解析其中之一。但是,执行第二个参数会导致泄漏,我知道原因:这是 malloc 在我的参数名称上的多次使用。
看一下解析代码:
int main()
{
int x;
char c;
char *nameTemp;
int hasName = 0;
int hasEqual = 0;
/* ParameterManager values */
ParameterManager *pm;
pm = PM_create(500);
if((PM_manage(pm, "name", INT_TYPE, 1)));
while((x = getchar()) != EOF)
{
/* Cast int to char */
c = (char)x;
/* Whitespace state */
if((isspace(c)))
{
c = whitespace();
}
/* Comment state */
if(c == '#')
{
c = comment();
}
/* Name state */
if(((isalnum(c)) && hasEqual == 0 && hasName == 0))
{
nameTemp = name(c);
printf("Name: %s\n", nameTemp);
hasName = 1;
}
/* Equal state */
if(c == '=' && hasName == 1 && hasEqual == 0)
{
hasEqual = 1;
}
/* Value state */
if((isalnum(c)) && hasName == 1 && hasEqual == 1)
{
getValues(c, nameTemp, pm->t_List, pm->m_List);
hasName = 0;
hasEqual = 0;
}
}
free(nameTemp);
if((PM_destroy(pm)) && DEBUG) printf("Success destroying PM.\n");
return 0;
}
行nameTemp = name(c)
,在/* Name state */
下,returns分配了一个字符串。这个字符串稍后被传递来做其他工作。但是,由于这整个解析思路是在循环中,所以会对同一个字符串进行多次mallocs。我只能释放 nameTemp 一次,但该名称上有多个 mallocs。我怎样才能一遍又一遍地重复使用 nameTemp 而不会造成任何泄漏?
这是一段代码(在函数 name()
中),其中分配了 nameTemp:
/* Make sure temp is not NULL before mallocing */
if(temp[0] != '[=12=]')
{
returnName = malloc(sizeof(char)*strlen(temp)+1);
strncpy(returnName, temp, strlen(temp)+1);
temp[0] = '[=12=]';
return returnName;
}
如果有几件事不清楚,我深表歉意。我尽量做到笼统,所以如果您需要更多说明,请告诉我。
malloc()
不跟踪分配的块。您需要找到完成处理您请求的内存的所有位置,然后 free()
它就在那里。
如果我没看错你的代码,那应该是在你的 while
循环主体的末尾。
编辑:调出评论。
尝试使用您已经 free()
的内存块是未定义的行为。
但是,您用来在块上保留句柄的 指针 只是一个常规指针,在将其传递给 free()
后不会过时.事实上,它根本不会移动,因为 free()
会复制它。
因此,在将指针传递给 free()
后,通常会看到该指针设置为 NULL
,以确保不会意外重用现在无法使用的块。
然后您可以像往常一样很好地重用它作为 malloc()
返回的全新块的句柄。
nameTemp = name(c);
导致不可避免的泄漏,当 nameTemp 存储一个指针时,该指针未保存在其他地方,此时也未释放。
有很多选择可以避免这种情况(取决于您想要实现的目标以及您愿意改变代码结构的程度)。
三种可能性(从最少到最多的代码更改量排序):
- 在再次分配之前释放内存(并在程序结束时再次释放它)
free(nameTemp);
nameTemp = name(c);
- 当内存过时时释放内存
/* Value state */
if((isalnum(c)) && hasName == 1 && hasEqual == 1)
{
getValues(c, nameTemp, pm->t_List, pm->m_List);
hasName = 0;
hasEqual = 0;
free(nameTemp);
nameTemp=NULL;
}
- 使用通用缓冲区,在开始时分配足够大的垃圾内存,并在结束时再次释放它。
char* nameTemp;
nameTemp = (char*)malloc(512); //Or any other size, just check that its actually big enough before writing to it, otherwise buffer overflow errors will occur.
// Somwhere in your program
write_name( nameTemp, 512 , c ); // Pass the buffer to be filled by the function, instead of returning a new pointer.
// At the end of your program
free(nameTemp);
nameTemp = NULL; //Prevent access of freed memory.