我试图通过分配所需内存加1并将最后一个元素设置为-1来获得C中整数数组的大小。然后我创建一个名为getSize的函数来确定数组中这个-1元素之前的元素数量,这是代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int getSize(int * array)
{
int i=0;
while(1)
{
if(array[i] == -1) return i;
else i++;
}
}
int main()
{
int * array = malloc(sizeof(int)*5);
memset(array,0,5);
array[4] = -1;
printf("nsize = %dn",getSize(array));
return 0;
}
这只是一个测试代码,但函数getSize
是更大代码的一部分,我在这个代码上运行了valgrind,这就是我遇到的问题:
===1683===条件跳转或移动取决于未初始化的值
===1683===在0x100000EAE:getSize(in./a.out)
===1683===通过0x100000F2E:主(输入/输出)
总结如下:
===1683===健康总结:
===1683===出口使用中:425个块中有38676个字节
===1683===总堆使用率:508个分配,83个释放,44948个字节分配泄漏总结:
===1683===肯定丢失:2个块中有36个字节
===1683===间接丢失:0个块中有0个字节
===1683===可能丢失:119个块中有13130个字节
===1683===仍然可访问:304个块中有25510个字节
===1683===已抑制:0个块中有0个字节
===1683===错误摘要:20个上下文中的22个错误(抑制:0到0)
这段代码中有几个问题。您展示的valgrind输出突出了两个问题。
===1683===条件跳转或移动取决于未初始化的值
===1683===在0x100000EAE:getSize(in./a.out)
===1683===通过0x100000F2E:主(输入/输出)
这是由getSize()中的if语句触发的
if(array[i] == -1) return i;
乍一看,这似乎还不错;在主函数中,使用malloc分配内存,然后使用memset将其清零,然后将最后一个元素设置为-1。
然而,让我们仔细看看
int * array = malloc(sizeof(int)*5);
memset(array,0,5);
您已经分配了足够大的空间来容纳5个整数,很可能是20个字节。然后尝试对其进行memset,但是memset当时对一个字节进行操作——换句话说,大小应该是以字节为单位的长度,而不是整数。所以,在这个操作之后,你得到了0’d的5个字节。内存的其余部分仍未初始化。
接下来使用数组表示法将最后一个整数设置为-1。这意味着您有一个20字节的缓冲区,前5个和后4个字节已初始化。
回到getSize函数,for循环中的第一次迭代很好,但第二次、第三次和第四次迭代读取未初始化的字节,并在此基础上执行条件跳转。
我们在valgrind输出中看到的第二个错误是内存泄漏。
泄漏总结:
===1683===肯定丢失:2个块中有36个字节
===1683===间接丢失:0个块中有0个字节
===1683===可能丢失:119个块中有13130个字节
===1683===仍然可访问:304个块中有25510个字节
===1683===已抑制:0个块中有0个字节
===1683===错误摘要:20个上下文中的22个错误(抑制:0到0)
在"绝对丢失"部分,它告诉我们您在2个块中丢失了36个字节。实际上,您提供的代码中只有一个漏洞,那就是为array
分配的内存。您需要添加以下行:
free(array);
在结束您的功能返回之前。Valgrind可以为您提供更多关于内存泄漏的详细信息——请在输出中查找提示。