有没有办法验证我的程序没有内存泄漏? [英] Is there way to verify my program has no memory leaks?
问题描述
我希望确定以下程序(查找最大子数组的实现)是否泄漏内存。有确定这种情况的一般方法吗?如使用调试器的某些功能?什么是一般策略?
I wish to determine if the following program (an implementation of finding the maximum sub-array) leaks memory. Is there a general way to determine this? Such as using some feature of a debugger? What are general strategies?
struct Interval {
int max_left;
int max_right;
int sum;
};
struct Interval * max_crossing_subarray(int A[], int low, int mid, int high) {
struct Interval * crossing = malloc(sizeof(struct Interval));
int left_sum = INT_MIN;
int sum = 0;
for(int i = mid; i >= low; --i) {
sum = sum + A[i];
if(sum > left_sum) {
left_sum = sum;
crossing->max_left = i;
}
}
int right_sum = INT_MIN;
sum = 0;
for(int j = mid+1; j <= high; ++j) {
sum = sum + A[j];
if(sum > right_sum) {
right_sum = sum;
crossing->max_right = j;
}
}
crossing->sum = left_sum + right_sum;
return crossing;
}
struct Interval * max_subarray(int A[], int low, int high) {
if(high == low) {
struct Interval * base = malloc(sizeof(struct Interval));
*base = (struct Interval) { low, high, A[low] };
return base;
} else {
int mid = floor((low+high)/2);
struct Interval * left = malloc(sizeof(struct Interval));
struct Interval * right = malloc(sizeof(struct Interval));
left = max_subarray(A, low, mid);
right = max_subarray(A, mid+1, high);
struct Interval * cross = max_crossing_subarray(A, low, mid, high);
if(left->sum >= right->sum & right->sum >= cross->sum) {
free(right);
free(cross);
return left;
} else if(right->sum >= left->sum & right->sum >= cross-> sum) {
free(left);
free(cross);
return right;
} else {
free(left);
free(right);
return cross;
}
}
}
int main()
{
int A[] = {-10, 7, -5, -3, 40, 4, -1, 8, -3, -1, -5, 20, 7};
struct Interval * result = max_subarray(A, 0, 12);
printf("left: %i, right: %i, sum: %i\n", result->max_left, result->max_right, result->sum);
return 0;
}
由于该程序具有递归性,因此很难遵循(至少为了我)。我想我已经插入了所有东西,但我想找到一种确定的方法。
Due to the recursive nature of the program it's quite difficult to follow (at least for me). I think I've plugged everything but I'd like to find a methodology for being sure.
编辑:软件建议在选定的答案中,我找到了所有的泄漏,并且正如注释中所指出的,没有理由左右分配,下面是无内存泄漏的代码。
struct Interval {
int max_left;
int max_right;
int sum;
};
struct Interval * max_crossing_subarray(int A[], int low, int mid, int high) {
struct Interval * crossing = malloc(sizeof(struct Interval));
int left_sum = INT_MIN;
int sum = 0;
for(int i = mid; i >= low; --i) {
sum = sum + A[i];
if(sum > left_sum) {
left_sum = sum;
crossing->max_left = i;
}
}
int right_sum = INT_MIN;
sum = 0;
for(int j = mid+1; j <= high; ++j) {
sum = sum + A[j];
if(sum > right_sum) {
right_sum = sum;
crossing->max_right = j;
}
}
crossing->sum = left_sum + right_sum;
return crossing;
}
struct Interval * max_subarray(int A[], int low, int high) {
if(high == low) {
struct Interval * base = malloc(sizeof(struct Interval));
*base = (struct Interval) { low, high, A[low] };
return base;
} else {
int mid = floor((low+high)/2);
struct Interval * left = max_subarray(A, low, mid);
struct Interval * right = max_subarray(A, mid+1, high);
struct Interval * cross = max_crossing_subarray(A, low, mid, high);
if(left->sum >= right->sum & right->sum >= cross->sum) {
free(right);
free(cross);
return left;
} else if(right->sum >= left->sum & right->sum >= cross-> sum) {
free(left);
free(cross);
return right;
} else {
free(left);
free(right);
return cross;
}
}
}
int main()
{
int A[] = {-10, 7, -5, -3, 40, 4, -1, 8, -3, -1, -5, 20, 7};
struct Interval * result = max_subarray(A, 0, 13-1);
printf("left: %i, right: %i, sum: %i\n", result->max_left, result->max_right, result->sum);
return 0;
}
推荐答案
您可以使用 valgrind 。这是用于Linux和其他类似UNIX的系统的内存调试工具,它可以查找内存泄漏以及无效的内存访问。
You can use valgrind. It's a memory debugging tool for Linux and other UNIX-like systems that finds memory leaks as well as invalid memory accesses.
当我通过valgrind运行此代码时,它会输出以下:
When I run this code through valgrind, it outputs the following:
[dbush@db-centos7 ~]$ valgrind ./x1
==3406== Memcheck, a memory error detector
==3406== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==3406== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==3406== Command: ./x1
==3406==
left: 4, right: 12, sum: 69
==3406==
==3406== HEAP SUMMARY:
==3406== in use at exit: 300 bytes in 25 blocks
==3406== total heap usage: 49 allocs, 24 frees, 588 bytes allocated
==3406==
==3406== LEAK SUMMARY:
==3406== definitely lost: 300 bytes in 25 blocks
==3406== indirectly lost: 0 bytes in 0 blocks
==3406== possibly lost: 0 bytes in 0 blocks
==3406== still reachable: 0 bytes in 0 blocks
==3406== suppressed: 0 bytes in 0 blocks
==3406== Rerun with --leak-check=full to see details of leaked memory
==3406==
==3406== For counts of detected and suppressed errors, rerun with: -v
==3406== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
所以您有一些泄漏。现在,让我们通过-leak-check = full
选项来查看那些泄漏的确切位置:
So you have some leaks. Now let's pass the --leak-check=full
option to see where exactly those leaks are:
==11531== Memcheck, a memory error detector
==11531== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==11531== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==11531== Command: ./x1
==11531==
left: 4, right: 12, sum: 69
==11531==
==11531== HEAP SUMMARY:
==11531== in use at exit: 300 bytes in 25 blocks
==11531== total heap usage: 49 allocs, 24 frees, 588 bytes allocated
==11531==
==11531== 12 bytes in 1 blocks are definitely lost in loss record 1 of 25
==11531== at 0x4C29EA3: malloc (vg_replace_malloc.c:309)
==11531== by 0x4007A8: max_subarray (x1.c:49)
==11531== by 0x400931: main (x1.c:73)
==11531==
==11531== 12 bytes in 1 blocks are definitely lost in loss record 2 of 25
==11531== at 0x4C29EA3: malloc (vg_replace_malloc.c:309)
==11531== by 0x4007B6: max_subarray (x1.c:50)
==11531== by 0x400931: main (x1.c:73)
==11531==
==11531== 12 bytes in 1 blocks are definitely lost in loss record 3 of 25
==11531== at 0x4C29EA3: malloc (vg_replace_malloc.c:309)
==11531== by 0x4007A8: max_subarray (x1.c:49)
==11531== by 0x4007CE: max_subarray (x1.c:51)
==11531== by 0x400931: main (x1.c:73)
==11531==
==11531== 12 bytes in 1 blocks are definitely lost in loss record 4 of 25
==11531== at 0x4C29EA3: malloc (vg_replace_malloc.c:309)
==11531== by 0x4007B6: max_subarray (x1.c:50)
==11531== by 0x4007CE: max_subarray (x1.c:51)
==11531== by 0x400931: main (x1.c:73)
==11531==
==11531== 12 bytes in 1 blocks are definitely lost in loss record 5 of 25
==11531== at 0x4C29EA3: malloc (vg_replace_malloc.c:309)
==11531== by 0x4007A8: max_subarray (x1.c:49)
==11531== by 0x4007CE: max_subarray (x1.c:51)
==11531== by 0x4007CE: max_subarray (x1.c:51)
==11531== by 0x400931: main (x1.c:73)
==11531==
==11531== 12 bytes in 1 blocks are definitely lost in loss record 6 of 25
==11531== at 0x4C29EA3: malloc (vg_replace_malloc.c:309)
==11531== by 0x4007B6: max_subarray (x1.c:50)
==11531== by 0x4007CE: max_subarray (x1.c:51)
==11531== by 0x4007CE: max_subarray (x1.c:51)
==11531== by 0x400931: main (x1.c:73)
==11531==
==11531== 12 bytes in 1 blocks are definitely lost in loss record 7 of 25
==11531== at 0x4C29EA3: malloc (vg_replace_malloc.c:309)
==11531== by 0x4007A8: max_subarray (x1.c:49)
==11531== by 0x4007CE: max_subarray (x1.c:51)
==11531== by 0x4007CE: max_subarray (x1.c:51)
==11531== by 0x4007CE: max_subarray (x1.c:51)
==11531== by 0x400931: main (x1.c:73)
==11531==
==11531== 12 bytes in 1 blocks are definitely lost in loss record 8 of 25
==11531== at 0x4C29EA3: malloc (vg_replace_malloc.c:309)
==11531== by 0x4007B6: max_subarray (x1.c:50)
==11531== by 0x4007CE: max_subarray (x1.c:51)
==11531== by 0x4007CE: max_subarray (x1.c:51)
==11531== by 0x4007CE: max_subarray (x1.c:51)
==11531== by 0x400931: main (x1.c:73)
==11531==
==11531== 12 bytes in 1 blocks are definitely lost in loss record 9 of 25
==11531== at 0x4C29EA3: malloc (vg_replace_malloc.c:309)
==11531== by 0x4007A8: max_subarray (x1.c:49)
==11531== by 0x4007E9: max_subarray (x1.c:52)
==11531== by 0x4007CE: max_subarray (x1.c:51)
==11531== by 0x4007CE: max_subarray (x1.c:51)
==11531== by 0x400931: main (x1.c:73)
==11531==
==11531== 12 bytes in 1 blocks are definitely lost in loss record 10 of 25
==11531== at 0x4C29EA3: malloc (vg_replace_malloc.c:309)
==11531== by 0x4007B6: max_subarray (x1.c:50)
==11531== by 0x4007E9: max_subarray (x1.c:52)
==11531== by 0x4007CE: max_subarray (x1.c:51)
==11531== by 0x4007CE: max_subarray (x1.c:51)
==11531== by 0x400931: main (x1.c:73)
==11531==
==11531== 12 bytes in 1 blocks are definitely lost in loss record 11 of 25
==11531== at 0x4C29EA3: malloc (vg_replace_malloc.c:309)
==11531== by 0x4007A8: max_subarray (x1.c:49)
==11531== by 0x4007E9: max_subarray (x1.c:52)
==11531== by 0x4007CE: max_subarray (x1.c:51)
==11531== by 0x400931: main (x1.c:73)
==11531==
==11531== 12 bytes in 1 blocks are definitely lost in loss record 12 of 25
==11531== at 0x4C29EA3: malloc (vg_replace_malloc.c:309)
==11531== by 0x4007B6: max_subarray (x1.c:50)
==11531== by 0x4007E9: max_subarray (x1.c:52)
==11531== by 0x4007CE: max_subarray (x1.c:51)
==11531== by 0x400931: main (x1.c:73)
==11531==
==11531== 12 bytes in 1 blocks are definitely lost in loss record 13 of 25
==11531== at 0x4C29EA3: malloc (vg_replace_malloc.c:309)
==11531== by 0x4007A8: max_subarray (x1.c:49)
==11531== by 0x4007CE: max_subarray (x1.c:51)
==11531== by 0x4007E9: max_subarray (x1.c:52)
==11531== by 0x4007CE: max_subarray (x1.c:51)
==11531== by 0x400931: main (x1.c:73)
==11531==
==11531== 12 bytes in 1 blocks are definitely lost in loss record 14 of 25
==11531== at 0x4C29EA3: malloc (vg_replace_malloc.c:309)
==11531== by 0x4007B6: max_subarray (x1.c:50)
==11531== by 0x4007CE: max_subarray (x1.c:51)
==11531== by 0x4007E9: max_subarray (x1.c:52)
==11531== by 0x4007CE: max_subarray (x1.c:51)
==11531== by 0x400931: main (x1.c:73)
==11531==
==11531== 12 bytes in 1 blocks are definitely lost in loss record 15 of 25
==11531== at 0x4C29EA3: malloc (vg_replace_malloc.c:309)
==11531== by 0x4007A8: max_subarray (x1.c:49)
==11531== by 0x4007E9: max_subarray (x1.c:52)
==11531== by 0x400931: main (x1.c:73)
==11531==
==11531== 12 bytes in 1 blocks are definitely lost in loss record 16 of 25
==11531== at 0x4C29EA3: malloc (vg_replace_malloc.c:309)
==11531== by 0x4007B6: max_subarray (x1.c:50)
==11531== by 0x4007E9: max_subarray (x1.c:52)
==11531== by 0x400931: main (x1.c:73)
==11531==
==11531== 12 bytes in 1 blocks are definitely lost in loss record 17 of 25
==11531== at 0x4C29EA3: malloc (vg_replace_malloc.c:309)
==11531== by 0x4007A8: max_subarray (x1.c:49)
==11531== by 0x4007CE: max_subarray (x1.c:51)
==11531== by 0x4007E9: max_subarray (x1.c:52)
==11531== by 0x400931: main (x1.c:73)
==11531==
==11531== 12 bytes in 1 blocks are definitely lost in loss record 18 of 25
==11531== at 0x4C29EA3: malloc (vg_replace_malloc.c:309)
==11531== by 0x4007B6: max_subarray (x1.c:50)
==11531== by 0x4007CE: max_subarray (x1.c:51)
==11531== by 0x4007E9: max_subarray (x1.c:52)
==11531== by 0x400931: main (x1.c:73)
==11531==
==11531== 12 bytes in 1 blocks are definitely lost in loss record 19 of 25
==11531== at 0x4C29EA3: malloc (vg_replace_malloc.c:309)
==11531== by 0x4007A8: max_subarray (x1.c:49)
==11531== by 0x4007CE: max_subarray (x1.c:51)
==11531== by 0x4007CE: max_subarray (x1.c:51)
==11531== by 0x4007E9: max_subarray (x1.c:52)
==11531== by 0x400931: main (x1.c:73)
==11531==
==11531== 12 bytes in 1 blocks are definitely lost in loss record 20 of 25
==11531== at 0x4C29EA3: malloc (vg_replace_malloc.c:309)
==11531== by 0x4007B6: max_subarray (x1.c:50)
==11531== by 0x4007CE: max_subarray (x1.c:51)
==11531== by 0x4007CE: max_subarray (x1.c:51)
==11531== by 0x4007E9: max_subarray (x1.c:52)
==11531== by 0x400931: main (x1.c:73)
==11531==
==11531== 12 bytes in 1 blocks are definitely lost in loss record 21 of 25
==11531== at 0x4C29EA3: malloc (vg_replace_malloc.c:309)
==11531== by 0x4007A8: max_subarray (x1.c:49)
==11531== by 0x4007E9: max_subarray (x1.c:52)
==11531== by 0x4007E9: max_subarray (x1.c:52)
==11531== by 0x400931: main (x1.c:73)
==11531==
==11531== 12 bytes in 1 blocks are definitely lost in loss record 22 of 25
==11531== at 0x4C29EA3: malloc (vg_replace_malloc.c:309)
==11531== by 0x4007B6: max_subarray (x1.c:50)
==11531== by 0x4007E9: max_subarray (x1.c:52)
==11531== by 0x4007E9: max_subarray (x1.c:52)
==11531== by 0x400931: main (x1.c:73)
==11531==
==11531== 12 bytes in 1 blocks are definitely lost in loss record 23 of 25
==11531== at 0x4C29EA3: malloc (vg_replace_malloc.c:309)
==11531== by 0x4007A8: max_subarray (x1.c:49)
==11531== by 0x4007CE: max_subarray (x1.c:51)
==11531== by 0x4007E9: max_subarray (x1.c:52)
==11531== by 0x4007E9: max_subarray (x1.c:52)
==11531== by 0x400931: main (x1.c:73)
==11531==
==11531== 12 bytes in 1 blocks are definitely lost in loss record 24 of 25
==11531== at 0x4C29EA3: malloc (vg_replace_malloc.c:309)
==11531== by 0x4007B6: max_subarray (x1.c:50)
==11531== by 0x4007CE: max_subarray (x1.c:51)
==11531== by 0x4007E9: max_subarray (x1.c:52)
==11531== by 0x4007E9: max_subarray (x1.c:52)
==11531== by 0x400931: main (x1.c:73)
==11531==
==11531== 12 bytes in 1 blocks are definitely lost in loss record 25 of 25
==11531== at 0x4C29EA3: malloc (vg_replace_malloc.c:309)
==11531== by 0x40065B: max_crossing_subarray (x1.c:13)
==11531== by 0x400802: max_subarray (x1.c:53)
==11531== by 0x400931: main (x1.c:73)
==11531==
==11531== LEAK SUMMARY:
==11531== definitely lost: 300 bytes in 25 blocks
==11531== indirectly lost: 0 bytes in 0 blocks
==11531== possibly lost: 0 bytes in 0 blocks
==11531== still reachable: 0 bytes in 0 blocks
==11531== suppressed: 0 bytes in 0 blocks
==11531==
==11531== For counts of detected and suppressed errors, rerun with: -v
==11531== ERROR SUMMARY: 25 errors from 25 contexts (suppressed: 0 from 0)
这些漏洞大多数即将到来从这两行开始:
Most of these leaks are coming from these two lines:
struct Interval * left = malloc(sizeof(struct Interval));
struct Interval * right = malloc(sizeof(struct Interval));
如果我们看一下下面两行,很明显为什么:
And if we look at the next two lines it's apparent why:
left = max_subarray(A, low, mid);
right = max_subarray(A, mid+1, high);
因此,在将分配的内存地址分配给这些指针之后,立即用其他值覆盖这些地址,造成泄漏。可以通过摆脱 malloc
调用并使用函数调用的结果进行初始化来解决此问题:
So right after you assign the address of allocated memory to these pointers you overwrite those addresses with other values, causing a leak. This can be fixed by getting rid of the malloc
calls and initializing with the result of the function calls:
struct Interval * left = max_subarray(A, low, mid);
struct Interval * right = max_subarray(A, mid+1, high);
最后一个在 max_crossing_subarray
struct Interval * crossing = malloc(sizeof(struct Interval));
此指针是从函数返回的,因此我们需要查看丢失的免费
是。环顾四周后,我们发现它是从 max_subarray
调用的,最终将其返回为 main
作为结果
:
This pointer is returned from the function, so we need to see where the missing free
is. After some looking around, we see that it is called from max_subarray
, which eventually returns it to main
as result
:
struct Interval * result = max_subarray(A, 0, 13-1);
printf("left: %i, right: %i, sum: %i\n", result->max_left, result->max_right, result->sum);
return 0;
但是正如您所看到的,没有人呼吁免费
在这里,所以我们添加它:
But as you can see, there's no call to free
here, so let's add it:
struct Interval * result = max_subarray(A, 0, 13-1);
printf("left: %i, right: %i, sum: %i\n", result->max_left, result->max_right, result->sum);
free(result);
return 0;
现在,在进行这些修复后,我们将再次通过valgrind进行操作:
Now after making those fixes we'll run through valgrind again:
==11736== Memcheck, a memory error detector
==11736== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==11736== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==11736== Command: ./x1
==11736==
left: 4, right: 12, sum: 69
==11736==
==11736== HEAP SUMMARY:
==11736== in use at exit: 0 bytes in 0 blocks
==11736== total heap usage: 25 allocs, 25 frees, 300 bytes allocated
==11736==
==11736== All heap blocks were freed -- no leaks are possible
==11736==
==11736== For counts of detected and suppressed errors, rerun with: -v
==11736== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
泄漏消失了。
这篇关于有没有办法验证我的程序没有内存泄漏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!