2

我有一个简单的程序来填充 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 的帖子,我正确地释放了我的数组。那么,为什么我会收到 hep 损坏异常?

4

2 回答 2

3

几件事:

  • 您需要malloc(size + 1)适合空终止符。
  • 没有必要做sizeof(char)-sizeof是根据 定义的char,所以永远是 1。
  • 您不应该强制转换结果malloc- 这是不必要的并且可能会隐藏问题。
  • 由于msgsArray未初始化,因此无法保证strlen(msgsArray[line]) == 0。事实上,它可能不会。如果您希望这是真的,请使用calloc而不是。malloc
  • 一般来说,使用strncpy代替strcpy- 它更安全。
  • 与其使用strlen,不如将char*s 初始化为null并检查null. 如果第一个msgToInsert是空字符串,但其余的是真实字符串怎么办?您的代码将退出循环,因为strlen(msgs[0]) == 0,检查null会修复。
于 2013-08-29T15:18:01.897 回答
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;  
    }
    
于 2013-08-29T15:34:02.870 回答