我试图通过分配所需的内存加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 = %d\n",getSize(array));
return 0;
}
这只是一个测试代码,但函数getSize
是更大代码的一部分,我在这段代码上运行了valgrind,这是我得到的问题:
== 1683 ==有条件的跳跃或移动取决于未初始化的值(s)
== 1683 ==在0x100000EAE:getSize(在./a.out)
== 1683 == by 0x100000F2E:main(在./a.out中)
以下是摘要:
== 1683 == HEAP SUMMARY:
== 1683 ==在退出时使用:425块中的38,676字节
== 1683 ==总堆使用量:508个分配,83个释放,44,948个字节分配泄漏概要:
== 1683 ==绝对丢失:2个区块中的36个字节
== 1683 ==间接丢失:0块中的0字节
== 1683 ==可能丢失:119块中的13,130字节
== 1683 ==仍然可达:304块中的25,510字节
== 1683 ==抑制:0块中的0字节
== 1683 ==错误摘要:来自20个上下文的22个错误(被抑制:0从0开始)
答案 0 :(得分:2)
此代码中存在几个问题。您展示的valgrind输出突出了两个问题。
== 1683 ==有条件的跳跃或移动取决于未初始化的值(s)
== 1683 ==在0x100000EAE:getSize(在./a.out)
== 1683 == by 0x100000F2E:main(在./a.out中)
这是由getSize()
中的if语句触发的if(array[i] == -1) return i;
乍一看似乎应该没问题;在main函数中,您使用malloc分配内存,然后使用memset将其归零,然后将最后一个元素设置为-1。
但是,让我们仔细看看
int * array = malloc(sizeof(int)*5);
memset(array,0,5);
你已经分配了足够大的空间来容纳5个整数,所以很可能是20个字节。然后尝试对此进行memset,但memset在当时对一个字节进行操作 - 换句话说,大小应该是以字节为单位的长度,而不是整数。 因此,在此操作之后,您将5个字节归零。其余的记忆仍未被初始化。
接下来,使用数组表示法将最后一个整数设置为-1。这意味着你有一个20字节的缓冲区,初始化前5个和后4个字节。
回到你的getSize函数,for循环中的第一次迭代很好,但是第二次,第三次和第四次迭代正在读取未经过许可的字节,并基于此执行条件跳转。
我们在valgrind输出中可以看到的第二个错误是你泄漏了内存。
泄漏概要:
== 1683 ==绝对丢失:2个区块中的36个字节
== 1683 ==间接丢失:0块中的0字节
== 1683 ==可能丢失:119块中的13,130字节
== 1683 ==仍然可达:304块中的25,510字节
== 1683 ==抑制:0块中的0字节
== 1683 ==错误摘要:来自20个上下文的22个错误(被抑制:0从0开始)
在绝对丢失的部分中,它告诉我们你在2个区块中丢失了36个字节。实际上,您提供的代码中只有一个泄漏,即为array
分配的内存。您需要添加以下行:
free(array);
从函数返回之前。 Valgrind可以为您提供有关内存泄漏的更多详细信息 - 查看输出中的提示。