AIX
系统作为IBM
公司PowerPC
架构的一款比较典型的操作系统,虽然随着Linux
的免费开源的普及,市面上几乎很少见,但仍然广泛存在于政府、银行、证券等核心系统中。由于该系统闭源,很多调试手段都无法在AIX
上有效运用,比如mtrace
、bcc
、valgrind
等,空有神力,却无法为之臂助。好在IBM
自己提供了一套内存泄漏的调试工具,可以比较方便的定位与调试。
当然,要想排查内存泄漏,首先我们得确认程序有没有内存泄漏。你可以使用诸如nmon
之类的监控工具持续观察某个程序内存的使用情况,看它有没有持续上涨。如果你没有安装nmon
,也可以使用系统命令去查看某个进程的内存占用情况:
svmon -P pid -o summary=basic,unit=MB
其中summary
是摘要的意思,表示要显示哪些信息,可选项有 basic | longreal | ame | longame
, 默认是basic
,如果你想了解该参数具体代表什么含义,可以参考:svmon Command - IBM Documentation,由于这个参数在本文不是重点,我们使用basic
就行了。
bash-5.0# svmon -P 7995550 -O summary=basic,unit=MB Unit: MB ------------------------------------------------------------------------------- Pid Command Inuse Pin Pgsp Virtual 7995550 flow 104.70 31.7 0 97.9
如果程序因为内存泄漏造成了核心转储,也就是所谓的coredump
,那么dbx
工具就派上用场了。dbx
对于调试coredump
文件,就像Linux
上使用gdb
一样丝滑。由于dbx
工具基本为Unix
系统自带,因此不仅适用于开发调试,在生产环境也有大大的用武之地。
通过dbx
的帮助信息,可以大致了解dbx
的使用方法:
bash-5.0# dbx -h dbx: fatal error: DBX Startup Options: dbx [-a ProcessID] [-B DebugFile] [-c CommandFile] [-I Directory] [ -E DebugEnvironment ] [-p [OldPath=NewPath:... | File]] [-v] [-u] [-x] [-F] [-L] [-r] [-C CoreFile | ObjectFile [CoreFile]] -a ProcessID Attach to specified process -c CommandFile Run dbx subcommands in specified file first -I Directory Include Directory in list of directories searched for source files -C CoreFile Allow to analyze core dump without ObjectFile -p OldPath=NewPath Substitute library path for core examination or when attaching to a process File Read library path substitutions for core examination or when attaching to a process from File -E DebugEnvironment Specifies the environment variable for the debug program -B DebugFile Specify an alternate debug file on startup -v Relax core file validity checking -u Prepend file name symbols with an '@' -x Strip postfix '_' from FORTRAN symbols -F Read all symbols at start-up time -L Keep linkage symbols -r Run object file immediately
dbx
的很多用法和gdb
类似,因此,有gdb
调试基础的人来说使用起来可能比较得心应手。这也是本文所使用的的主要的调试手段。
为了更好地演示dbx
是如何工作的,我在这里准备 了一个示例代码:
//leak.c #include<string.h> #include<stdio.h> #include<stdlib.h> #include<malloc.h> void func1(); void func2(); void main() { while(1) func1(); } void func1() { func2(); } void func2() { char *str; str=(char *) malloc(1024*1024); strcpy(str,"testing"); }
上面是一段非常简单的代码,我们在main
函数里不断地调用func1
函数 ,又在func1
函数里调用func2
函数 ,每次调用func2
函数,都会申请1MB
空间大小的内存,该内存并没有释放 ,也就是说,只要main
不终止,就会一直申请下去。
我们运行该段程序,很快,程序就coredump
了。
bash-5.0# ./leak Segmentation fault (core dumped)
如果你的程序没有出现coredump
,那很有可能是ulimit
没有设置,需要设置ulimit -c
参数,它代表的是生成corefile
的最大size
:
ulimit -c unlimited
如果一切设置正确的话,你会在当前目录得到一个core
文件。我们可以使用dbx
对它进行调试,使用命令为:
dbx process corefile
运行上述命令后 ,可以得到如下信息:
bash-5.0# dbx ./leak core Type 'help' for help. [using memory image in core] reading symbolic information ...internal error: unexpected value 120 at line 5176 in file stabstring.c internal error: 1283-228 expected char ',', found 's__LC_locale:,768,32;__meth_ptr:92,800,32;__data_ptr:92,832,32;;' internal error: 1283-228 expected char ',', found '__LC_locale:,768,32;__meth_ptr:92,800,32;__data_ptr:92,832,32;;' internal error: 1283-228 expected char ';', found '_LC_locale:,768,32;__meth_ptr:92,800,32;__data_ptr:92,832,32;;' internal error: unexpected value 44 at line 5176 in file stabstring.c internal error: 1283-228 expected char ',', found '768,32;__meth_ptr:92,800,32;__data_ptr:92,832,32;;' internal error: unexpected value 120 at line 5176 in file stabstring.c internal error: unexpected value 120 at line 5176 in file stabstring.c internal error: 1283-228 expected char ',', found 's_LC_locale_objhdl:,64,32;;' internal error: 1283-228 expected char ',', found '_LC_locale_objhdl:,64,32;;' internal error: 1283-228 expected char ';', found 'LC_locale_objhdl:,64,32;;' internal error: unexpected value 44 at line 5176 in file stabstring.c internal error: 1283-228 expected char ',', found '64,32;;' internal error: unexpected value 120 at line 5176 in file stabstring.c internal error: unexpected value 120 at line 5176 in file stabstring.c internal error: unexpected value 120 at line 5176 in file stabstring.c internal error: unexpected value 120 at line 5176 in file stabstring.c internal error: unexpected value 120 at line 5176 in file stabstring.c internal error: unexpected value 120 at line 5176 in file stabstring.c internal error: unexpected value 120 at line 5176 in file stabstring.c Segmentation fault in func2 at line 20 in file "leak.c" 20 strcpy(str,"testing"); (dbx) where func2(), line 20 in "leak.c" func1(), line 14 in "leak.c" main(), line 10 in "leak.c" (dbx)
以上信息已经报告了出现coredump
的位置。位于leak.c
的第20
行,func2
函数中,strcpy(str,"testing")
这一句代码。你可能仍然不理解,strcpy
为什么会造成核心转储,我们继续往下调试:
(dbx) p str (nil)
当我们打印str
的值的时候,得到的是nil
,也就是 说 ,在19
行,执行str=(char *) malloc(1024*1024);
申请内存的时候,没有成功,为了验证这一点,我们将原始代码修改一下:
#include<string.h> #include<stdio.h> #include<stdlib.h> #include<malloc.h> void func1(); void func2(); static int mem_size = 0; void main() { while(1) func1(); } void func1() { func2(); } void func2() { char *str; int size = 1024*1024; str=(char *) malloc(size); if (str == NULL) { printf("malloc %d bytes memory failed, total malloc size is %d bytes\n", size, mem_size); exit(-1); } else { mem_size += size; } strcpy(str,"testing"); }
执行后出现如下结果:
bash-5.0# ./leak malloc 1048576 bytes memory failed, total malloc size is 267386880 bytes bash-5.0#
可见,确实是申请内存失败了。同时,我们也注意到total memory
是267386880
,这个大小正好是255M
。也就是说,前255M
内存申请都成功了,在第256
次申请的时候失败了。
这个256M
的限制其实 和AIX
系统 上32
位应用程序的数据段大小有关。在AIX
上,进程数据段大小主要通过LDR_CNTRL
环境变量设置,而LDR_CNTRL
这个环境变量的值,往往是和MAXDATA
值进行绑定的 。如果你想了解更详细的内容,请参考:进程内存大小限制 (ibm.com)。
那么 ,为什么是256M
呢 ?我们回到最原始的代码版本。仍然使用dbx
打开core
文件, 使用proc rlimit
可以看到ulimit
的限制值。该参数看到的往往和直接在命令行输入ulimit -a
看到的一致,不过这种方式展示的是进程的更详细的信息。
(dbx) proc rlimit rlimit name: rlimit_cur rlimit_max (units) RLIMIT_CPU: (unlimited) (unlimited) sec RLIMIT_FSIZE: 1073741312 1073741312 bytes RLIMIT_DATA: 2147483648 (unlimited) bytes RLIMIT_STACK: 33554432 4294967296 bytes RLIMIT_CORE: (unlimited) (unlimited) bytes RLIMIT_RSS: 33554432 (unlimited) bytes RLIMIT_AS: (unlimited) (unlimited) bytes RLIMIT_NOFILE: 2000 (unlimited) descriptors RLIMIT_THREADS: (unlimited) (unlimited) per process RLIMIT_NPROC: (unlimited) (unlimited) per user (dbx)
可以看到 ,RLIMIT_DATA
最大值为unlimited
,这说明可用堆内存是没有被限制的。我们可以在dbx
外面,使用dump
命令查看MAXDATA
值:
bash-5.0# dump -Xany -ov ./leak ./leak: ***Object Module Header*** # Sections Symbol Ptr # Symbols Opt Hdr Len Flags 5 0x0000c9ee 1532 72 0x1002 Flags=( EXEC DYNLOAD DEP_SYSTEM ) Timestamp = "Mar 21 13:49:17 2022" Magic = 0x1df (32-bit XCOFF) ***Optional Header*** Tsize Dsize Bsize Tstart Dstart 0x00000d4d 0x0000042b 0x00000218 0x10000150 0x20000e9d SNloader SNentry SNtext SNtoc SNdata 0x0004 0x0002 0x0001 0x0002 0x0002 TXTalign DATAalign TOC vstamp entry 0x0005 0x0004 0x20001244 0x0001 0x200011f4 maxSTACK maxDATA SNbss magic modtype 0x00000000 0x00000000 0x0003 0x010b 1L
可以看到 ,最后一行 ,maxDATA
显示是0x00000000
,对于32
位应用来说,0x00000000
是一个默认设置,它和0x10000000
是等价的,代表1*28大小的内存,即256M
,如果超过这个数值,就会出现核心转储。
作为示例,我们不妨将其调大点,设置成0x20000000
,也即512M
。
bash-5.0# LDR_CNTRL=MAXDATA=0x20000000 ./leak Segmentation fault (core dumped)
它同样会发生 coredump
,我们主要关心一下它所能申请的内存大小。这次我们直接进入dbx
去查看。
(dbx) malloc The following options are enabled: Implementation Algorithm........ Default Allocator (Yorktown) Statistical Report on the Malloc Subsystem: Heap 0 heap lock held by................ UNLOCKED bytes acquired from sbrk()....... 535895568 bytes in the freespace tree...... 65056 bytes held by the user........... 535830512 allocations currently active..... 511 allocations since process start.. 511 The Process Heap Initial process brk value........ 0x300014e0 current process brk value........ 0x4ff132f0 sbrk()s called by malloc......... 481 (dbx)
我们 重点关注bytes held by the user
,它代表由用户申请但没有被释放的内存,可以看到其大小为535830512
,大约是511M
多一点。这是符合我们的预期的。
这种方式其实比使用where
命令更能确定是否是内存泄漏问题造成的coredump
,因为对于一些比较复杂的程序来说 ,有可能的确正常的业务处理就要占用超过256M
内存,这时候就无法定位是正常业务内存申请导致的coredump
,还是内存泄漏导致的。
而malloc
命令很明显就是查看的malloc
申请的堆内存大小, bytes held by the user
的意思也很直观。但这种查看手段无法定位是哪一行代码出现了问题。我们当然可以两种手段结合起来看,这里我们提供另外一种调试思路。即使用MALLOCDEBUG
来记录内存申请的相关 信息。
使用也很简单:
export MALLOCDEBUG=log:extended,stack_depth:20 <start process> unset MALLOCDEBUG
extended
参数提供了一些额外的信息,比如分配的时间、线程ID等,在多线程调试时很有用。但一般是非必需的。stack_depth
代表的是调用栈的深度,如果程序调用的函数层数比较多的话,那么可以设置多一点,可以动态调整。一般来说,20
已经够用了。
bash-5.0# export MALLOCDEBUG=log:extended,stack_depth:20 bash-5.0# ./leak Segmentation fault (core dumped) bash-5.0# unset MALLOCDEBUG
执行完后,使用dbx
打开core
文件, 输入malloc allocation
,可以看到比较详细的信息:
(dbx) malloc allocation Allocations Held by the Process: ADDRESS SIZE HEAP PID PTHREAD_T CLOCKTIME SEQ STACK TRACEBACK 0x200204e8 1048576 0 2294034 0x00000000 1647844961 0 0xd01f27b4 malloc_common_debugging 0xd01288ec init_malloc 0xd012a234 malloc 0x10000558 func2 0x1000050c func1 0x100004d8 main 0x100001bc __start 0x201204f8 1048576 0 2294034 0x00000000 1647844961 1 0xd01f27b4 malloc_common_debugging 0x10000558 func2 0x1000050c func1 0x100004d8 main 0x100001bc __start 0x20220508 1048576 0 2294034 0x00000000 1647844961 2 0xd01f27b4 malloc_common_debugging 0x10000558 func2 0x1000050c func1 0x100004d8 main 0x100001bc __start 0x20320518 1048576 0 2294034 0x00000000 1647844961 3 0xd01f27b4 malloc_common_debugging 0x10000558 func2 0x1000050c func1 0x100004d8 main 0x100001bc __start ...more
以上信息大部分是重复的,我们可以选取其中一个查看,得到的有用信息是,malloc
申请内存是在执行main
函数时,每次调用func1
函数,然后在func1
里调用func2
函数,在 func2
里进行的内存分配,我们甚至能看到分配的内存大小,为1048576
,即1MB
。
从这些信息 ,我们 大致就能定位 出,内存泄漏很可能出现在func2
函数中。因此,我们只需要排查func2
函数中malloc
的内存是否及时释放就行了。
当然,上面这个例子过于简单,因为只有这一个地方使用了malloc
申请内存,因此定位起来还是非常快的 。但实际的企业级代码中 ,调用malloc
的地方可能有很多,不可能非常方便地找到到底是哪个地方申请 的内存出现了泄漏。如下面的程序:
//leak2.c #include<string.h> #include<stdlib.h> void func1(); void func2(); void main() { char *a,*b,*c,*d; a = (char *) malloc (1024*1024); b = (char *) calloc (4, 64); c = (char *) malloc (1024*1024*3); d = (char *) malloc (256); d = (char *) realloc(d, 16); while(1) func1(); free(a); free(b); free(c); free(d); } void func1() { char *e; e = calloc(1, 1024*1024); func2(); free(e); } void func2() { char *str, *p; p = (char *) malloc(256); str=(char *) malloc(1024*1024); strcpy(str,"testing"); free(p); }
以上这个程序就稍微复杂一点,不仅在多处都有malloc
的调用,而且还有realloc
以及calloc
的调用。
运行这个程序,很明显也会产生coredump
。我们使用上面的方式打开core
文件:
bash-5.0# dbx ./leak2 core Type 'help' for help. [using memory image in core] reading symbolic information ...internal error: unexpected value 120 at line 5176 in file stabstring.c internal error: 1283-228 expected char ',', found 's__LC_locale:,768,32;__meth_ptr:92,800,32;__data_ptr:92,832,32;;' internal error: 1283-228 expected char ',', found '__LC_locale:,768,32;__meth_ptr:92,800,32;__data_ptr:92,832,32;;' internal error: 1283-228 expected char ';', found '_LC_locale:,768,32;__meth_ptr:92,800,32;__data_ptr:92,832,32;;' internal error: unexpected value 44 at line 5176 in file stabstring.c internal error: 1283-228 expected char ',', found '768,32;__meth_ptr:92,800,32;__data_ptr:92,832,32;;' internal error: unexpected value 120 at line 5176 in file stabstring.c internal error: unexpected value 120 at line 5176 in file stabstring.c internal error: 1283-228 expected char ',', found 's_LC_locale_objhdl:,64,32;;' internal error: 1283-228 expected char ',', found '_LC_locale_objhdl:,64,32;;' internal error: 1283-228 expected char ';', found 'LC_locale_objhdl:,64,32;;' internal error: unexpected value 44 at line 5176 in file stabstring.c internal error: 1283-228 expected char ',', found '64,32;;' internal error: unexpected value 120 at line 5176 in file stabstring.c internal error: unexpected value 120 at line 5176 in file stabstring.c internal error: unexpected value 120 at line 5176 in file stabstring.c internal error: unexpected value 120 at line 5176 in file stabstring.c internal error: unexpected value 120 at line 5176 in file stabstring.c internal error: unexpected value 120 at line 5176 in file stabstring.c internal error: unexpected value 120 at line 5176 in file stabstring.c Segmentation fault in func2 at line 33 in file "leak2.c" 33 strcpy(str,"testing"); (dbx) malloc allocation Allocations Held by the Process: ADDRESS SIZE HEAP ALLOCATOR 0x200015f8 1048584 0 YORKTOWN 0x20101608 264 0 YORKTOWN 0x20101718 3145736 0 YORKTOWN 0x20401728 24 0 YORKTOWN 0x20401748 1048584 0 YORKTOWN 0x20501758 264 0 YORKTOWN 0x20501868 1048584 0 YORKTOWN 0x20601878 1048584 0 YORKTOWN 0x20701888 1048584 0 YORKTOWN 0x20801898 1048584 0 YORKTOWN 0x209018a8 1048584 0 YORKTOWN 0x20a018b8 1048584 0 YORKTOWN 0x20b018c8 1048584 0 YORKTOWN 0x20c018d8 1048584 0 YORKTOWN 0x20d018e8 1048584 0 YORKTOWN 0x20e018f8 1048584 0 YORKTOWN 0x20f01908 1048584 0 YORKTOWN 0x21001918 1048584 0 YORKTOWN 0x21101928 1048584 0 YORKTOWN ...more
如上图所示,虽然我们能看出有很多1048584
字节的内存申请,但并不能定位到是哪个地方泄漏造成的。这时候我们可以将allocation
信息dump
出来,操作十分简单,只需要在malloc allocation
后面重定向到一个文件即可:
(dbx) malloc allocation > allocs.out
这样在本地就会产生一个allocs.out
文件,当然这个文件我们仍然是无法直接分析的,这时候可以借助一些脚本来辅助分析,比如我们可以写一个如下的awk
脚本:
#!/bin/awk -f function sort(ARRAY, ELEMENTS, temp, i, j) { for (i = 2; i <= ELEMENTS; ++i) { for (j = i; ARRAY[j-1] > ARRAY[j]; --j) { temp = ARRAY[j] ARRAY[j] = ARRAY[j-1] ARRAY[j-1] = temp } } return } BEGIN{ sum=0; check[0,0]=0 arr[0]=0 i=0 } { if((match($1,"^0x[2-9a]") && length($1)==10) || (match($1,"^0x0") && length($1)==18)){ sum+=$2; if(check[$2,0] == 1){ check[$2,1]++ # print $2 "*" check[$2,1] } else { arr[i++]=$2 check[$2,0] = 1 check[$2,1] = 1 } } } END{ ind=0 n=0 print "Final Result" sort(arr,i) for(j=0;j<=i;j++){ ind=arr[j]; # print ind " " check[ind,1] " and " ind*check[ind,1] print "Total: " ind*check[ind,1] " Size of allocation: " ind " Frequency of allocation: " check[ind,1] } print sum }
运行这个脚本,可以得到如下结果:
bash-5.0# ./alloc.awk allocs.out Final Result Total: 0 Size of allocation: Frequency of allocation: Total: 272 Size of allocation: 136 Frequency of allocation: 2 Total: 72 Size of allocation: 72 Frequency of allocation: 1 Total: 264 Size of allocation: 264 Frequency of allocation: 1 Total: 267388920 Size of allocation: 1048584 Frequency of allocation: 255 267389528
从以上结果,可以看出,我们一共申请了2
次136
字节的内存,1
次72
字节的内存,1
次264
字节的内存,以及255
次内存,每次申请1048584
字节,一共申请了267389528
字节(255M
)。这样很容易就能判断出出问题的是这255
次申请的大内存。
但是在实际的场景中,内存的频繁申请和释放会导致分析变得异常困难,尤其是涉及到第三方库的时候,因为我们无法把控第三方库是怎么实现的,以及它们是如何编译出来的,如果第三方库有内存泄漏,那么用上面的方法,可能就不是那么友好了。
这时候,仍然要祭出MALLOCDEBUG
大杀器。
比如我们看到的信息如下:
0x000000011010c290 1114112 0 17236260 0x00000102 1533826269 1270 0x00900000000053ec0 malloc_common_debugging 0x0090000002172f890 sqloGetPrivateMemoryFromOs__FPPvCUlCUiCP12SMemLogEvent 0x009000000217330ac allocateChunkGroup__7SMemSetF9SqloChunkT1UiCP12SMemResource 0x00900000021645d10 getChunksFromTree__7SMemSetF9SqloChunkT1CPUiPP9SChunkGrpP9SqloC 0x009000000216447c8 getContiguousChunks__7SMemSetF9SqloChunkCPUiPP9SChunkGrpP9SqloC 0x0090000002178be7c getNewChunkSubgroup__13SQLO_MEM_POOLFCUlUiT1CP12SMemLogEventPP1 0x00900000021790878 allocateMemoryBlock__13SQLO_MEM_POOLFCUlT1UiT1PP17SqloChunkSubg 0x00900000021726824 sqloGetMemoryBlockExtended 0x00900000021724168 sqlo_init_generic_data_temp__FP15sql_static_dataCUlT2CbP19SqloR 0x009000000219cc170 sqlo_create_init_EDU_data_temp__FUiP19SqloResourceBinding 0x00000000100001688 DB2main 0x00900000021706194 sqloEDUMainEntry__FPcUi 0x009000000217058b0 sqloEDUEntry 0x00900000000598fec _pthread_body
上面这段信息告诉我们sqloGetPrivateMemoryFromOs__FPPvCUlCUiCP12SMemLogEvent
申请了一块大内存,那么这个函数属于哪个第三方库呢?我们可以使用map
命令来查看:
(dbx) map 0x0090000002172f890 Entry 61: Object name: ./db2/db2sox/DB2_11.1_FP2/lib64/libdb2e.a Member name: shr_64.o Text origin: 0x90000002158f000 Text length: 0x10e1bded Data origin: 0x9001000a540b1d8 Data length: 0x2d8e818 File descriptor: 0x7d
即这个函数是db2/db2sox/DB2_11.1_FP2/lib64/libdb2e.a
中的,如果你认定第三方库存在内存泄漏,那么就说明和你自己的代码关系不大,要么,你给官方提issue
,要么不用人家的库,换个更靠谱的实现。
当然了,还有更麻烦的,因为第三方库我们拿来用的时候,可能本身只是一个.a
或者.so
,谁也不知道是怎么编译出来的,用的什么编译器,有没有开启编译器优化,所以最终我们看到的内容可能是这样子的,出现一堆问号,压根不知道是哪个函数调用引起的:
0x2006e138 12 0 8716372 0x00000000 1535042884 270 0xd01b1854 malloc_common_debugging 0xd193a4a8 ?? 0xd193af9c ?? 0xd193dea0 ?? 0xd19550fc ?? 0xd196cabc ?? 0xd1a3b340 ?? 0xd1a3b180 ?? 0x1007c6e8 ssh_OpenSSL_add_all_algorithms 0x10004604 main 0x10000214 __start
这时,我们可以借助一个叫listi
的命令来查看:
(dbx) listi 0xd193a4a8 0xd193a4a8 (default_malloc_ex+0x18) 80410014 lwz r2,0x14(r1) 0xd193a4ac (default_malloc_ex+0x1c) 81810048 lwz r12,0x48(r1) 0xd193a4b0 (default_malloc_ex+0x20) 38210040 addi r1,0x40(r1) 0xd193a4b4 (default_malloc_ex+0x24) 7d8803a6 mtlr r12 0xd193a4b8 (default_malloc_ex+0x28) 4e800020 blr
这个命令会以汇编的方式将该地址展开,从以上信息中,我们可以看到调用的函数是default_malloc_ex
,然后拿到0xd193a4a8
地址后,就可以使用map
命令来判断到底哪个第三方库的问题了。
注意事项
前面提到,AIX
定位内存泄漏的主要手段是调试生成的core
文件;而前面又提到过,生成core
文件的阈值是由LDR_CNTRL
环境变量决定的。那么,这也就对core
文件的生成提出了比较高的要求。
首先引出的问题是,如果LDR_CNTRL
设置的比较大,如2G
,程序短时间内并不会达到这么大的内存,因此也不会主动core
掉,这时候如果你发现内存是在缓慢上升,那么该如何判断是否是内存泄漏呢?
其实这时候我们可以手动生成一个core
文件,生成方式如下:
gencore <PID of process> /<directory>/core
如果你觉得生成core
文件比较麻烦,你也可以直接attach
到正在运行的进程上,命令如下:
dbx -a <PID>
具体使用和gdb
类似,这里就不多赘述了。
第二个问题,我们必须保证core
文件是完整的,残缺的core
文件是无法调试的,这样的core
文件有还不如没有。
那么如何保证core
文件的完整呢?首先我们可以修改ulimit
参数,这点和Linux
下一样。
ulimit -c unlimited
如果想永久生效,则可以修改/etc/security/limits
文件。当然还可以通过chdev -l sys0 -a fullcore=true
命令来允许生成完整的core文件(参考[Enabling full AIX core files - IBM Documentation](Enabling full AIX core files - IBM Documentation))。
还有一点就是,MALLOCDEBUG
虽然好用,但会带来额外的CPU
和内存开销,适用于开发环境调试,但不适用于生产环境长时间运行。否则你以为为啥这个参数不默认放开呢?
本专栏知识点是通过<零声教育>的系统学习,进行梳理总结写下文章,对C/C++课程感兴趣的读者,可以点击链接,查看详细的服务:C/C++Linux服务器开发/高级架构师