释放2D动态数组时堆积损坏

时间:2013-08-29 15:10:54

标签: c arrays malloc free

我有一个简单的程序,用于填充2D动态字符数组。分配像往常一样工作。我的问题依赖于释放数组。我在VC ++ 2008上使用纯C。

当我分配和初始化我的数组时,这是一段代码:

char** messsages = (char**)malloc(5*sizeof(char*));
initValorArrayMsgs(messsages, 5);

insertMsgToArray(5, messsages , "Test message.");

void insertMsgToArray(int totalLines, char** msgsArray, const char* msgToInsert)
{
    int line = 0;
    int size= strlen(msgToInsert);

    for(; line < totalLines; line ++)
    {
        if(strlen(msgsArray[line ]) == 0)
        {
            msgsArray[line ] = (char*)malloc(sizeof(char) * size);
            strcpy(msgsArray[line], msgToInsert);
            break;
        }
    }
}

这是我释放数组的代码

void freeArrayMsgs(char** arry, int lines)
{
    int i = 0;
    for(; i < lines; i++)
    {
        if(strlen(arry[i]) == 0){
            break;
        }
        free(arry[i]);
    }
    free(arry);
}

当程序试图释放第一个数组时,它会引发堆腐败异常。

在SO上阅读一些帖子,我正在解放我的阵列。那么,为什么我会得到肝脏腐败例外?

2 个答案:

答案 0 :(得分:3)

一些事情:

  • 您需要malloc(size + 1)以适应空终结符。
  • 无需执行sizeof(char) - sizeofchar定义,因此始终为1。
  • 您不应该投射malloc的结果 - 这是不必要的,可能会隐藏问题。
  • 由于msgsArray未初始化,因此无法保证strlen(msgsArray[line]) == 0。事实上,它可能不会。如果您希望这样做,请使用calloc代替malloc
  • 一般情况下,使用strncpy代替strcpy - 它更安全。
  • 最好将strlen初始化为char*并检查null,而不是使用null。如果第一个msgToInsert是一个空字符串,但其余的是真正的字符串怎么办?您的代码将退出循环,因为strlen(msgs[0]) == 0会检查null而不是修复。

答案 1 :(得分:0)

有两件事突然袭来我:

  1. freeArrayMsgs的内部逻辑似乎是可疑的:在第一个NULL指针上,它会停止循环。

     for ( ;  i < lines;  i++)  
     {  
         if (strlen (arry[i]) == 0)  
             break;  
         free (arry[i]);  
     }
    

    也许这没关系,但如果lines是有史以来使用的最大值,那么将它们全部搞定就很重要了。请注意,释放偶数NULL指针是完全正确的 - 这样做是无操作的。

  2. 如果代码重用了指针,那么在free()之后它真的应该将它们清空。如果我看到代码中隐含的相同哲学在整个代码中都存在,那么您可能会重用一个释放的指针,因为存储的指针不是NULL。这很容易解决:

    for ( ;  i < lines;  i++)  
    {  
        free (arry[i]);  
        arry[i] = NULL;  
    }