一、报错信息
[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调试的方式,也可以把有问题的函数注释掉,看还报不报错,之后再根据情况具体问题具体分析,主要是还是多测试不同的数据和多思考。