以前上课的时候,老师总是说全局变量不要随便用,当时也只是记得这个说法,至于为什么也没仔细研究。结果最近写代码的时候果断跪了。
其实内存泄露跟全局变量的使用没有因果关系,只不过是我在写代码的时候犯2了。下面是我在做深度优先搜索的时候写的一段代码:
void dfs(int c)
{
//error 2
int i;
if(c == c2)
{
if(path == dist[c2])
{
count += 1;
if(max < hand)
{
max = hand;
}
}
return;
}
if(path > dist[c2])
return;
for(i=0;i<n;i++)
{
if(arcs[c][i]!=INFINITY && !s[i])
{
path += arcs[c][i];
hand += teams[i];
s[i] = 1;
dfs(i);
path -= arcs[c][i];
hand -= teams[i];
s[i] = 0;
}
}
}
代码中的数组都是指针通过malloc动态申请的,这些指针都是全局变量。为了图方便,我把i,j这些变量也直接声明成全局变量了。结果问题来了。在DFS代码中忘记重新声明一个i变量用于迭代了,而i这个变量作为全局变量还在,导致编译的时候也不会找到这个错误。如果是C++倒是可能不会有这个问题,一般在for循环内部我都重新声明i变量。
就算是i用的是全局变量,最有可能也是逻辑上得到的结果是错误的,为什么会出现内存泄露这种不相关的错误呢?arcs是n*n的数组,这里假设n=5。那么在for循环第一次i等于0,假设arcs[0][1]是有路径的,也就是说能够进入if内的逻辑。那么根据深度搜索那么下一次递归调用dfs的时候,参数就变成了1。再对1做深度搜索的时候,不管for内部的if是否成立,for迭代都是要做完的。这样迭代完了之后i的值一定是5(n=5),然后返回上一层,此时上一层i的值理应为1,但是由于i是全局变量,此时i的值是5。看dfs(i)下一句
path -= arcs[c][i];
按理说应该取的是arcs[c][1],但是结果却取成了arcs[c][5],又因为arcs在申请空间的时候取的是5×5,这样一来,直接就造成了数组越界,所以在最后free这个指针的时候才会导致内存泄露。因为实际上使用的空间与申请的空间已经不一致了。