c-如何回收和重用已分配的内存



我现在正在做的是为流中的任何输入提供一个基于状态的解析器。我的教授告诉我这是避免特殊情况的最好方法。我设置它的方式是使用函数,并且我在尝试重用分配的内存时遇到了一些麻烦,这样我就不会造成任何泄漏。我分析的是多个参数。每个参数都有一个名称和一个值。一个示例输入是:

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: %sn", 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;
}

/* Name state */下的行nameTemp = name(c)返回一个已分配的字符串。此字符串稍后被传递以执行其他工作。然而,由于整个解析思想是循环的,因此将对同一字符串进行多个malloc。我只能释放nameTemp一次,但该名称上有多个mallocs。如何反复使用nameTemp而不造成任何泄漏?

以下是分配nameTemp的一段代码(在函数name()中):

 /* Make sure temp is not NULL before mallocing */
    if(temp[0] != '')
    {
        returnName = malloc(sizeof(char)*strlen(temp)+1);
        strncpy(returnName, temp, strlen(temp)+1);
        temp[0] = '';
        return returnName;
    }

如果有几点不清楚,我深表歉意。我正在尽可能地概括,所以如果你需要更多的澄清,请告诉我。

malloc()不跟踪分配的块。你需要找到所有处理完你请求的内存的地方,并在那里free()

如果我正确地阅读了您的代码,那么它将位于while循环的末尾。

编辑:调出评论。

尝试使用已经free()'d的内存块是未定义的行为。

但是,用于保持块句柄的指针只是一个常规指针,在将其传递给free()后不会过时。事实上,它根本不会移动,因为free()会复制它。

因此,常见的是在所述指针被传递到free()之后将其设置为NULL,以确保不会意外地重用现在不可用的块。

然后,您可以像往常一样,很好地重用它作为malloc()返回的全新块的句柄。

nameTemp = name(c);在nameTemp存储指针时会导致不可避免的泄漏,该指针没有保存在其他地方,此时也没有释放。

有很多选择可以避免这种情况(取决于您试图实现的目标以及您愿意在多大程度上更改代码结构)。

三种可能性(从最少的代码更改到最多的代码更改):

  1. 在再次分配内存之前释放内存(并在程序结束时再次释放)
free(nameTemp);
nameTemp = name(c);
  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);
    nameTemp=NULL;
}
  1. 使用通用缓冲区,在开始时分配足够大的内存垃圾,并在结束时再次释放
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.

相关内容

  • 没有找到相关文章

最新更新