在这个for循环中导致内存泄漏的原因是什么?

时间:2012-01-21 04:19:56

标签: c

for(k=i; k<MAXRECORDS; k++) {
    if(slist->servers_ptr[k+1] != NULL) {
        slist->servers_ptr[k] = slist->servers_ptr[k+1];
    } else slist->servers_ptr[k] = NULL;
}

当我运行valgrind时,出现无效大小8的错误。

请注意MAXRECORDS = 10,数组大小为MAXRECORDS

我认为这与我的for循环中的边框情况有关,但我不明白它是如何发生的。

编辑:有人指出,在for循环的最后一轮中,访问servers_ptr[k+1]在数组之外,导致valgrind错误。我已经将我的代码更新为:

for(k=i; k<MAXRECORDS-1; k++) {
    if(slist->servers_ptr[k+1] != NULL) {
            slist->servers_ptr[k] = slist->servers_ptr[k+1];
            if(k==MAXRECORDS-2)slist->servers_ptr[k+1] = NULL;
    } else slist->servers_ptr[k] = NULL;
}

我仍然在valgrind中得到错误。我错误地更新了吗?

1 个答案:

答案 0 :(得分:3)

servers_ptr的大小为MAXRECORDS。在for循环的最后一次迭代中,k == MAX_RECORDS - 1。您可以访问servers_ptr[k+1] servers_ptr[MAX_RECORDS],它是一个超出数组末尾的 for(k=i; k<MAXRECORDS; k++) { if(slist->servers_ptr[k+1] != NULL) { slist->servers_ptr[k] = slist->servers_ptr[k+1]; } else slist->servers_ptr[k] = NULL; } 。这是未定义的行为,valgrind标记它。

slist->servers_ptr[k] = slist->servers_ptr[k+1];

考虑那个else子句。它与以下相同:

slist->server_ptr[k+1]

因为我们知道 for(k=i; k<MAXRECORDS; k++) { slist->servers_ptr[k] = slist->servers_ptr[k+1]; } 为NULL,因为我们失败了if条件。但这意味着if的两个分支都是相同的。所以代码相当于:

[1][2][3][4][5]
[2][3][4][5][?]

所以你正在做的是将所有指针移动到左边:

            for(k=i; k<MAXRECORDS-1; k++) {
                slist->servers_ptr[k] = slist->servers_ptr[k+1];
            }
            slist->servers_ptr[MAXRECORDS-1] = NULL;

您的代码尝试将一个值转换为多个并最终从某个地方提取垃圾。

解决方案是复制少一个项目并将最后一个单元格作为特例处理。

{{1}}