C - 大输入时内存泄漏

时间:2015-06-05 14:28:04

标签: c memory-leaks valgrind

对于作业,我必须订购一份学生名单。每个都用一个数字(大小为15的字符串),他父亲的姓氏(字符串20),他母亲的姓氏(字符串20)和他的名字(字符串20)表示。

我做了一个程序,从一个文件构建学生列表并订购它(我使用合并排序)。

当我在少数学生(<10 000)上运行程序时,一切都很好(没有内存泄漏或根据valgrind的任何内容)。

然而,一旦我尝试在较大的(超过10万)上使用它,我就会出现分段错误11.我使用Valgrind进行了调查,它说错误来自strcy或strcasecmp函数,并呈现:

==2433== Invalid write of size 8
==2433==    at 0x4019BD: merge (sort.c:59)
==2433==    by 0x40173B: sortBeginEnd (sort.c:38)
==2433==    by 0x4014B0: sortWithoutInterval (sort.c:9)
==2433==    by 0x401EE0: firstSort (sort.c:166)
==2433==    by 0x4009EB: main (main.c:44)
==2433==  Address 0xffe79ac88 is on thread 1's stack
==2433== 
==2433== 
==2433== Process terminating with default action of signal 11 (SIGSEGV)
==2433==  Access not within mapped region at address 0xFFE79AC88
==2433==    at 0x4019BD: merge (sort.c:59)
==2433==  If you believe this happened as a result of a stack
==2433==  overflow in your program's main thread (unlikely but
==2433==  possible), you can try to increase the size of the
==2433==  main thread stack using the --main-stacksize= flag.
==2433==  The main thread stack size used in this run was 8388608.
==2433== 
==2433== Process terminating with default action of signal 11 (SIGSEGV)
==2433==  Access not within mapped region at address 0xFFE79AC81
==2433==    at 0x4A256B0: _vgnU_freeres (in /usr/lib/valgrind/vgpreload_core-amd64-linux.so)
==2433==  If you believe this happened as a result of a stack
==2433==  overflow in your program's main thread (unlikely but
==2433==  possible), you can try to increase the size of the
==2433==  main thread stack using the --main-stacksize= flag.
==2433==  The main thread stack size used in this run was 8388608.
==2433== 
==2433== HEAP SUMMARY:
==2433==     in use at exit: 12,800,101 bytes in 500,007 blocks
==2433==   total heap usage: 500,008 allocs, 1 frees, 12,800,669 bytes allocated
==2433== 
==2433== LEAK SUMMARY:
==2433==    definitely lost: 0 bytes in 0 blocks
==2433==    indirectly lost: 0 bytes in 0 blocks
==2433==      possibly lost: 0 bytes in 0 blocks
==2433==    still reachable: 12,800,101 bytes in 500,007 blocks
==2433==         suppressed: 0 bytes in 0 blocks
==2433== Rerun with --leak-check=full to see details of leaked memory
==2433== 
==2433== For counts of detected and suppressed errors, rerun with: -v
==2433== ERROR SUMMARY: 7452721 errors from 31 contexts (suppressed: 0 from 0)

错误可能是我使用了太多内存(每个学生代表79个字符= 316个字节,我有100 000个,所以如果我是对的话,它是31 600 000个字节)?

PS:我对堆栈和堆的概念并不十分熟悉

编辑:

“一切都很好”valgrind报道:

==2454== 
==2454== HEAP SUMMARY:
==2454==     in use at exit: 0 bytes in 0 blocks
==2454==   total heap usage: 50,008 allocs, 50,008 frees, 1,280,669 bytes allocated
==2454== 
==2454== All heap blocks were freed -- no leaks are possible
==2454== 
==2454== For counts of detected and suppressed errors, rerun with: -v
==2454== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

EDIT2:

如果您想检查代码,可以使用here

编辑最后:

由于@Lundin的回答,我终于找到了解决方案。问题是我没有使用malloc为mergeSort的合并部分分配临时数组。

我将进一步研究堆/堆栈的问题,以便完全理解这个问题。

2 个答案:

答案 0 :(得分:3)

您甚至没有提到这是哪个系统。因为Valgrind我假设Linux。您没有提到分配变量的位置。显然不在堆上,因为Valgrid只报告12.8kb。

如果我没记错的话(我对Linux知之甚少),进程的堆栈大小约为8Mb。

316 *  10000 =  3.16 Mb. 
316 * 100000 = 31.60 Mb. 

合格的猜测:如果你以除malloc以外的任何其他方式分配变量,那么堆栈溢出就是所描述问题的根源。

每当在程序中使用大量内存时,必须在堆上动态分配它们。

答案 1 :(得分:1)

堆栈是您的函数保存其本地/临时数据(参数和局部变量)的位置。它被组织成一堆文件,因此当你调用一个函数时,参数被放到堆栈中,当函数完成时,除了结果之外的所有东西都会从堆栈中被丢弃。通常堆栈的大小有限。

堆是内存,保存分配的数据(f.e. malloc())。您可以拥有不同的堆(适用于您的应用程序,适用于每个流程和系统范围)