C语言-报错集锦-03-malloc(): memory corruption: 0x0000000001496d90 ***

文章描述了一个程序在执行过程中遇到的内存错误,报错信息指向`malloc()`,经过gdb调试发现是由于数组越界访问导致的内存溢出。作者强调错误可能源于对内存的误操作,如数组边界问题,需仔细检查代码并进行充分测试。
摘要由CSDN通过智能技术生成

一、报错信息

[2023-8]--[ Debug ]--Push Data To StAccessPath OK.
[2023-8]--[ Debug ]--Judge Vertex(0) Is Not Accessed.
[2023-8]--[ Debug ]--Judge Vertex(2) Is Accessed.
[2023-8]--[ Debug ]--Judge Vertex(3) Is Not Accessed.
[2023-8]--[ Debug ]--Judge Vertex(4) Is Accessed.
[2023-8]--[ Debug ]--Judge Vertex(5) Is Not Accessed.
[2023-8]--[ Debug ]--Judge Vertex(6) Is Accessed.
[2023-8]--[ Debug ]--Judge Vertex(7) Is Accessed.
[2023-8]--[ Debug ]--Judge Vertex(8) Is Not Accessed.
[2023-8]--[ Debug ]--Judge Vertex(9) Is Not Accessed.
[2023-8]--[ Debug ]--Judge Vertex(10) Is Not Accessed.
[2023-8]--[ Debug ]--Judge Vertex(11) Is Not Accessed.
[2023-8]--[ Debug ]--Push Data To Lowest Edge Array OK.
[2023-8]--[ Debug ]--ReturnWeightVal : 32767, Find All Access Path Ahead Of Time.
[2023-8]--[ Debug ]--No Need To Traverse, Find OK, i : 1, StartVertexIndex : 1
[2023-8]--[ Debug ]--Push Data To StDijkstraAccees OK.
*** Error in `./TestGraph': malloc(): memory corruption: 0x0000000001496d90 ***
======= Backtrace: =========
/lib64/libc.so.6(+0x82b36)[0x7f48f5257b36]
/lib64/libc.so.6(__libc_malloc+0x4c)[0x7f48f525a78c]
./TestGraph[0x400fb9]
./TestGraph[0x400dda]
./TestGraph[0x405f2a]
./TestGraph[0x4062ba]
./TestGraph[0x406700]
./TestGraph[0x40700e]
/lib64/libc.so.6(__libc_start_main+0xf5)[0x7f48f51f7555]
./TestGraph[0x400829]
======= Memory map: ========
00400000-0040a000 r-xp 00000000 fd:00 2549952                            /opt/Developer/ComputerLanguageStudy/C/DataStructureTestSrc/Graph/TestGraph
00609000-0060a000 r--p 00009000 fd:00 2549952                            /opt/Developer/ComputerLanguageStudy/C/DataStructureTestSrc/Graph/TestGraph
0060a000-0060b000 rw-p 0000a000 fd:00 2549952                            /opt/Developer/ComputerLanguageStudy/C/DataStructureTestSrc/Graph/TestGraph
01493000-014b4000 rw-p 00000000 00:00 0                                  [heap]
7f4890000000-7f4890021000 rw-p 00000000 00:00 0 
7f4890021000-7f4894000000 ---p 00000000 00:00 0 
7f48959f8000-7f4895a0d000 r-xp 00000000 fd:00 33554509                   /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7f4895a0d000-7f4895c0c000 ---p 00015000 fd:00 33554509                   /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7f4895c0c000-7f4895c0d000 r--p 00014000 fd:00 33554509                   /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7f4895c0d000-7f4895c0e000 rw-p 00015000 fd:00 33554509                   /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7f4895c0e000-7f48f51d5000 rw-p 00000000 00:00 0 
7f48f51d5000-7f48f5399000 r-xp 00000000 fd:00 33780350                   /usr/lib64/libc-2.17.so
7f48f5399000-7f48f5598000 ---p 001c4000 fd:00 33780350                   /usr/lib64/libc-2.17.so
7f48f5598000-7f48f559c000 r--p 001c3000 fd:00 33780350                   /usr/lib64/libc-2.17.so
7f48f559c000-7f48f559e000 rw-p 001c7000 fd:00 33780350                   /usr/lib64/libc-2.17.so
7f48f559e000-7f48f55a3000 rw-p 00000000 00:00 0 
7f48f55a3000-7f48f55c5000 r-xp 00000000 fd:00 33780343                   /usr/lib64/ld-2.17.so
7f48f57be000-7f48f57c4000 rw-p 00000000 00:00 0 
7f48f57c4000-7f48f57c5000 r--p 00021000 fd:00 33780343                   /usr/lib64/ld-2.17.so
7f48f57c5000-7f48f57c6000 rw-p 00022000 fd:00 33780343                   /usr/lib64/ld-2.17.so
7f48f57c6000-7f48f57c7000 rw-p 00000000 00:00 0 
7ffc944b9000-7ffc944db000 rw-p 00000000 00:00 0                          [stack]
7ffc94516000-7ffc94518000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
已放弃(吐核)

二、问题分析

[gbase@czg2 Graph]$ gdb TestGraph core.57248 
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-120.el7
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /opt/Developer/ComputerLanguageStudy/C/DataStructureTestSrc/Graph/TestGraph...done.
[New LWP 57248]
Core was generated by `./TestGraph'.
Program terminated with signal 6, Aborted.
#0  0x00007f48f520b387 in raise () from /lib64/libc.so.6
Missing separate debuginfos, use: debuginfo-install glibc-2.17-326.el7_9.x86_64 libgcc-4.8.5-44.el7.x86_64
(gdb) bt
#0  0x00007f48f520b387 in raise () from /lib64/libc.so.6
#1  0x00007f48f520ca78 in abort () from /lib64/libc.so.6
#2  0x00007f48f524df67 in __libc_message () from /lib64/libc.so.6
#3  0x00007f48f5257b36 in _int_malloc () from /lib64/libc.so.6
#4  0x00007f48f525a78c in malloc () from /lib64/libc.so.6
#5  0x0000000000400fb9 in MyMalloc (size=2048) at ../PublicFunction/PublicFunction.c:50
#6  0x0000000000400dda in LogFormat (PrintLevel=4, StrFormat=0x407fb0 "%s\n") at ../Log/Log.c:130
#7  0x0000000000405f2a in PushData2StDijkstraAccees (StDA=0x1495c50, InsertNodeIndex=3, StartIndex=2, EndIndex=4, Weight=1) at ShortestPath.c:303
#8  0x00000000004062ba in StatisticsStDijkstraAccees (StDks=0x1496460, StDA=0x1495c50, StartVertexIndex=1) at ShortestPath.c:353
#9  0x0000000000406700 in DijkstraAlgorithm (AMG=0x7f4895c0e010, StDA=0x1495c50, StartVertexIndex=1) at ShortestPath.c:437
#10 0x000000000040700e in main () at main.c:77
(gdb) 

函数调用栈中的第4层发现和malloc有关,第一个想法难道触发malloc的BUG了,应该不会,毕竟malloc都是大佬实现的,上一层的MyMalloc和LogFormat都是我自己封装的,使用了这么久都没有问题,那就看一下最近的函数实现吧,实在不行再从这两个函数出发,先从第7帧的PushData2StDijkstraAccees看起。

(gdb) f 7
#7  0x0000000000405f2a in PushData2StDijkstraAccees (StDA=0x1495c50, InsertNodeIndex=3, StartIndex=2, EndIndex=4, Weight=1) at ShortestPath.c:303
303         LogFormat(Debug, "%s\n", "Push Data To StDijkstraAccees OK.");
(gdb) l PushData2StDijkstraAccees
277         LogFormat(Debug, "%s\n", "Push Data To Lowest Edge Array OK.");
278         return SuccessFlag;
279     }
280
281     Status PushData2StDijkstraAccees(StDijkstraAccees* StDA, VertexIndexType InsertNodeIndex, VertexIndexType StartIndex, VertexIndexType EndIndex, WeightType Weight)
282     {
283         JudgeAllNullPointer(StDA);
284
285         if (InsertNodeIndex >= StDA->AccessPathMaxLen)
286         {
(gdb) 
287             LogFormat(Error, "Parameter InsertNodeIndex(%d) Need < AccessPathMaxLen(%d), Exit.\n", InsertNodeIndex, StDA->AccessPathMaxLen);
288             exit(ExceptionExitFlag);
289         }
290
291         if (StDA->AccessPath[InsertNodeIndex]->AccessArrayLen == StDA->AccessPath[InsertNodeIndex]->AccessArrayMaxLen)
292         {
293             LogFormat(Error, "AccessPath[%d] Is Full, AccessArrayMaxLen : %d, Exit.\n", InsertNodeIndex, StDA->AccessPath[InsertNodeIndex]->AccessArrayMaxLen);
294             exit(ExceptionExitFlag);
295         }
296         
(gdb) 
297         StDA->AccessPath[InsertNodeIndex]->AccessArray[StDA->AccessPath[InsertNodeIndex]->AccessArrayLen].StartVertexIndex = StartIndex;
298         StDA->AccessPath[InsertNodeIndex]->AccessArray[StDA->AccessPath[InsertNodeIndex]->AccessArrayLen].EndVertexIndex   = EndIndex;
299         StDA->AccessPath[InsertNodeIndex]->AccessArray[StDA->AccessPath[InsertNodeIndex]->AccessArrayLen].Weight           = Weight;
300
301         StDA->AccessPath[InsertNodeIndex]->AccessArrayLen++;
302
303         LogFormat(Debug, "%s\n", "Push Data To StDijkstraAccees OK.");
304         return SuccessFlag;    
305     }
306
(gdb) p InsertNodeIndex
$1 = 3
(gdb) p StartIndex
$2 = 2
(gdb) p EndIndex
$3 = 4
(gdb) p Weight
$4 = 1
(gdb) set print pretty on
(gdb) p *StDA
$5 = {
  AccessPath = 0x1495c70, 
  AccessPathMaxLen = 11
}
(gdb) p StDA->AccessPath[InsertNodeIndex]->AccessArrayLen
$6 = 1
(gdb) p StDA->AccessPath[InsertNodeIndex]->AccessArray[0]
$7 = {
  StartVertexIndex = 2, 
  EndVertexIndex = 4, 
  Weight = 1
}

访问都正常,数据写入也都正常,难道问题不在这一层中,看看上一层的函数StatisticsStDijkstraAccees。

(gdb) f 8
#8  0x00000000004062ba in StatisticsStDijkstraAccees (StDks=0x1496460, StDA=0x1495c50, StartVertexIndex=1) at ShortestPath.c:353
353             PushData2StDijkstraAccees(StDA, 
(gdb) l StatisticsStDijkstraAccees
304         return SuccessFlag;    
305     }
306
307     //统计起始节点到各个节点的访问路径。
308     Status StatisticsStDijkstraAccees(StDijkstra* StDks, StDijkstraAccees* StDA, VertexIndexType StartVertexIndex)
309     {
310         JudgeAllNullPointer(StDks);
311         JudgeAllNullPointer(StDA);   
312
313         VertexIndexType  i            = 0;
(gdb) 
314         VertexIndexType  j            = 0;
315         VertexIndexType  x            = 0;
316         VertexIndexType  TmpIndex     = 0;//临时变量,存放顶点索引信息。
317         VertexIndexType* VisitedArray = (VertexIndexType*)MyMalloc(StDks->PathLenArrayLen * sizeof(VertexIndexType));//存放已经命中的索引。
318
319         for (i = 0; i < StDks->PathLenArrayMaxLen; i++)
320         {
321             //LogFormat(Debug,"i : %d, StartVertexIndex : %d\n",i,StartVertexIndex);
322
323             if (StDks->LowestEdgeArray[i].AccessPath->AccessArrayLen == 0)//访问节点数组长度为0时,跳过。
(gdb) 
324             {
325                 continue;
326             }
327             
328             //LogFormat(Debug,"(%d,%d,%d,%d,%d,%d)\n",VisitedArray[0],VisitedArray[1],VisitedArray[2],VisitedArray[3],VisitedArray[4],VisitedArray[5]);
329             //取最外层的顶点信息,如果起始节点等于传入的起始节点索引,不需要寻找其祖先顶点。
330             if (StDks->LowestEdgeArray[i].AccessPath->AccessArray[StDks->LowestEdgeArray[i].AccessPath->AccessArrayLen - 1].StartVertexIndex == StartVertexIndex)
331             {
332                 LogFormat(Debug, "No Need To Traverse, Find OK, i : %d, StartVertexIndex : %d\n",i,StartVertexIndex);
333                 PushData2StDijkstraAccees(StDA, 
(gdb) 
334                                           i, 
335                                           StartVertexIndex, 
336                                           StDks->LowestEdgeArray[i].AccessPath->AccessArray[StDks->LowestEdgeArray[i].AccessPath->AccessArrayLen - 1].EndVertexIndex, 
337                                           StDks->LowestEdgeArray[i].AccessPath->AccessArray[StDks->LowestEdgeArray[i].AccessPath->AccessArrayLen - 1].Weight);
338                 continue;
339             }
340
341             for ( x = 0; x < StDks->PathLenArrayMaxLen; x++)//初始化VisitedArray数据
342             {
343                 if (StDks->LowestEdgeArray[i].AccessPath->AccessArrayLen == 0)
(gdb) 
344                 {
345                     VisitedArray[x] = VISITED_FLAG;
346                 }
347                 else
348                 {
349                     VisitedArray[x] = NOT_VISITED_FLAG;
350                 }
351             }
352             
353             PushData2StDijkstraAccees(StDA, 
(gdb) 
354                                 i, 
355                                 StDks->LowestEdgeArray[i].AccessPath->AccessArray[StDks->LowestEdgeArray[i].AccessPath->AccessArrayLen - 1].StartVertexIndex, 
356                                 StDks->LowestEdgeArray[i].AccessPath->AccessArray[StDks->LowestEdgeArray[i].AccessPath->AccessArrayLen - 1].EndVertexIndex, 
357                                 StDks->LowestEdgeArray[i].AccessPath->AccessArray[StDks->LowestEdgeArray[i].AccessPath->AccessArrayLen - 1].Weight);
358             VisitedArray[i] = VISITED_FLAG;
359             TmpIndex        = StDks->LowestEdgeArray[i].AccessPath->AccessArray[StDks->LowestEdgeArray[i].AccessPath->AccessArrayLen - 1].StartVertexIndex;
360             j               = 0;
361
362             while (TmpIndex != StartVertexIndex)
363             {
(gdb) p StDks->PathLenArrayLen
$26 = 4
(gdb) p StDks->PathLenArrayMaxLen
$27 = 11

发现问题了,317行VisitedArray长度为4,341行开始初始化了11次,数组越界访问了,然后插入数据的时候就崩了。将VisitedArray的申请长度变为11,就正常了。

三、总结

malloc(): memory corruption错误不一定和malloc有关,可能是因为哪里对内存进行了误操作,例如:数组越界访问并使用,也有可能导致。像我这个问题就是能够稳定复现的,如果不喜欢gdb调试的方式,也可以把有问题的函数注释掉,看还报不报错,之后再根据情况具体问题具体分析,主要是还是多测试不同的数据和多思考。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值