《coredump问题原理探究》Linux x86版7.6节 Map coredump例子

定位一个map相关的coredump来熟悉一下:

Core was generated by `./xuzhina_dump_c07_s3_ex 5 / 6'.
Program terminated with signal 11, Segmentation fault.
#0  0x00000000 in ?? ()
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.149.el6_6.4.i686 libgcc-4.4.7-11.el6.i686 libstdc++-4.4.7-11.el6.i686
(gdb) bt
#0  0x00000000 in ?? ()
#1  0x08048bd0 in main ()
(gdb) i r 
eax            0x5	5
ecx            0x0	0
edx            0x0	0
ebx            0x6	6
esp            0xbfd3de7c	0xbfd3de7c
ebp            0xbfd3dee8	0xbfd3dee8
esi            0x0	0
edi            0x0	0
eip            0x0	0
eflags         0x210296	[ PF AF SF IF RF ID ]
cs             0x73	115
ss             0x7b	123
ds             0x7b	123
es             0x7b	123
fs             0x0	0
gs             0x33	51

由于栈顶的指令地址为0x0,而eip的值也是0x0,可以知道是调用了函数指针,且函数指针的值为空.而这个函数指针是由main函数调用

看一下main函数的汇编:

(gdb) disassemble 
Dump of assembler code for function main:
   0x0804898f <+0>:	push   %ebp
   0x08048990 <+1>:	mov    %esp,%ebp
   0x08048992 <+3>:	and    $0xfffffff0,%esp
   0x08048995 <+6>:	push   %esi
   0x08048996 <+7>:	push   %ebx
   0x08048997 <+8>:	sub    $0x58,%esp
   0x0804899a <+11>:	cmpl   $0x3,0x8(%ebp)
   0x0804899e <+15>:	jg     0x80489b6 <main+39>
   0x080489a0 <+17>:	movl   $0x8049ce4,(%esp)
   0x080489a7 <+24>:	call   0x804883c <puts@plt>
   0x080489ac <+29>:	mov    $0xffffffff,%ebx
   0x080489b1 <+34>:	jmp    0x8048c42 <main+691>
   0x080489b6 <+39>:	lea    0x18(%esp),%eax
   0x080489ba <+43>:	mov    %eax,(%esp)
   0x080489bd <+46>:	call   0x8048c6e <_ZNSt3mapISsPFiiiESt4lessISsESaISt4pairIKSsS1_EEEC2Ev>
   0x080489c2 <+51>:	lea    0x37(%esp),%eax
   0x080489c6 <+55>:	mov    %eax,(%esp)
   0x080489c9 <+58>:	call   0x804887c <_ZNSaIcEC1Ev@plt>
   0x080489ce <+63>:	lea    0x37(%esp),%eax
   0x080489d2 <+67>:	mov    %eax,0x8(%esp)
   0x080489d6 <+71>:	movl   $0x8049cfa,0x4(%esp)
---Type <return> to continue, or q <return> to quit---
   0x080489de <+79>:	lea    0x30(%esp),%eax
   0x080489e2 <+83>:	mov    %eax,(%esp)
   0x080489e5 <+86>:	call   0x80487ec <_ZNSsC1EPKcRKSaIcE@plt>
   0x080489ea <+91>:	lea    0x30(%esp),%eax
   0x080489ee <+95>:	mov    %eax,0x4(%esp)
   0x080489f2 <+99>:	lea    0x18(%esp),%eax
   0x080489f6 <+103>:	mov    %eax,(%esp)
   0x080489f9 <+106>:	call   0x8048cfc <_ZNSt3mapISsPFiiiESt4lessISsESaISt4pairIKSsS1_EEEixERS5_>
   0x080489fe <+111>:	movl   $0x8048964,(%eax)
   0x08048a04 <+117>:	lea    0x30(%esp),%eax
   0x08048a08 <+121>:	mov    %eax,(%esp)
   0x08048a0b <+124>:	call   0x80487cc <_ZNSsD1Ev@plt>
   0x08048a10 <+129>:	jmp    0x8048a41 <main+178>
   0x08048a12 <+131>:	mov    %edx,%ebx
   0x08048a14 <+133>:	mov    %eax,%esi
   0x08048a16 <+135>:	lea    0x30(%esp),%eax
   0x08048a1a <+139>:	mov    %eax,(%esp)
   0x08048a1d <+142>:	call   0x80487cc <_ZNSsD1Ev@plt>
   0x08048a22 <+147>:	mov    %esi,%eax
   0x08048a24 <+149>:	mov    %ebx,%edx
   0x08048a26 <+151>:	jmp    0x8048a28 <main+153>
   0x08048a28 <+153>:	mov    %edx,%ebx
---Type <return> to continue, or q <return> to quit---
   0x08048a2a <+155>:	mov    %eax,%esi
   0x08048a2c <+157>:	lea    0x37(%esp),%eax
   0x08048a30 <+161>:	mov    %eax,(%esp)
   0x08048a33 <+164>:	call   0x804882c <_ZNSaIcED1Ev@plt>
   0x08048a38 <+169>:	mov    %esi,%eax
   0x08048a3a <+171>:	mov    %ebx,%edx
   0x08048a3c <+173>:	jmp    0x8048c26 <main+663>
   0x08048a41 <+178>:	lea    0x37(%esp),%eax
   0x08048a45 <+182>:	mov    %eax,(%esp)
   0x08048a48 <+185>:	call   0x804882c <_ZNSaIcED1Ev@plt>
   0x08048a4d <+190>:	lea    0x3f(%esp),%eax
   0x08048a51 <+194>:	mov    %eax,(%esp)
   0x08048a54 <+197>:	call   0x804887c <_ZNSaIcEC1Ev@plt>
   0x08048a59 <+202>:	lea    0x3f(%esp),%eax
   0x08048a5d <+206>:	mov    %eax,0x8(%esp)
   0x08048a61 <+210>:	movl   $0x8049cfc,0x4(%esp)
   0x08048a69 <+218>:	lea    0x38(%esp),%eax
   0x08048a6d <+222>:	mov    %eax,(%esp)
   0x08048a70 <+225>:	call   0x80487ec <_ZNSsC1EPKcRKSaIcE@plt>
   0x08048a75 <+230>:	lea    0x38(%esp),%eax
   0x08048a79 <+234>:	mov    %eax,0x4(%esp)
   0x08048a7d <+238>:	lea    0x18(%esp),%eax
   0x08048a81 <+242>:	mov    %eax,(%esp)
---Type <return> to continue, or q <return> to quit---
   0x08048a84 <+245>:	call   0x8048cfc <_ZNSt3mapISsPFiiiESt4lessISsESaISt4pairIKSsS1_EEEixERS5_>
   0x08048a89 <+250>:	movl   $0x8048972,(%eax)
   0x08048a8f <+256>:	lea    0x38(%esp),%eax
   0x08048a93 <+260>:	mov    %eax,(%esp)
   0x08048a96 <+263>:	call   0x80487cc <_ZNSsD1Ev@plt>
   0x08048a9b <+268>:	jmp    0x8048acc <main+317>
   0x08048a9d <+270>:	mov    %edx,%ebx
   0x08048a9f <+272>:	mov    %eax,%esi
   0x08048aa1 <+274>:	lea    0x38(%esp),%eax
   0x08048aa5 <+278>:	mov    %eax,(%esp)
   0x08048aa8 <+281>:	call   0x80487cc <_ZNSsD1Ev@plt>
   0x08048aad <+286>:	mov    %esi,%eax
   0x08048aaf <+288>:	mov    %ebx,%edx
   0x08048ab1 <+290>:	jmp    0x8048ab3 <main+292>
   0x08048ab3 <+292>:	mov    %edx,%ebx
   0x08048ab5 <+294>:	mov    %eax,%esi
   0x08048ab7 <+296>:	lea    0x3f(%esp),%eax
   0x08048abb <+300>:	mov    %eax,(%esp)
   0x08048abe <+303>:	call   0x804882c <_ZNSaIcED1Ev@plt>
   0x08048ac3 <+308>:	mov    %esi,%eax
   0x08048ac5 <+310>:	mov    %ebx,%edx
   0x08048ac7 <+312>:	jmp    0x8048c26 <main+663>
---Type <return> to continue, or q <return> to quit---
   0x08048acc <+317>:	lea    0x3f(%esp),%eax
   0x08048ad0 <+321>:	mov    %eax,(%esp)
   0x08048ad3 <+324>:	call   0x804882c <_ZNSaIcED1Ev@plt>
   0x08048ad8 <+329>:	lea    0x47(%esp),%eax
   0x08048adc <+333>:	mov    %eax,(%esp)
   0x08048adf <+336>:	call   0x804887c <_ZNSaIcEC1Ev@plt>
   0x08048ae4 <+341>:	lea    0x47(%esp),%eax
   0x08048ae8 <+345>:	mov    %eax,0x8(%esp)
   0x08048aec <+349>:	movl   $0x8049cfe,0x4(%esp)
   0x08048af4 <+357>:	lea    0x40(%esp),%eax
   0x08048af8 <+361>:	mov    %eax,(%esp)
   0x08048afb <+364>:	call   0x80487ec <_ZNSsC1EPKcRKSaIcE@plt>
   0x08048b00 <+369>:	lea    0x40(%esp),%eax
   0x08048b04 <+373>:	mov    %eax,0x4(%esp)
   0x08048b08 <+377>:	lea    0x18(%esp),%eax
   0x08048b0c <+381>:	mov    %eax,(%esp)
   0x08048b0f <+384>:	call   0x8048cfc <_ZNSt3mapISsPFiiiESt4lessISsESaISt4pairIKSsS1_EEEixERS5_>
   0x08048b14 <+389>:	movl   $0x8048983,(%eax)
   0x08048b1a <+395>:	lea    0x40(%esp),%eax
   0x08048b1e <+399>:	mov    %eax,(%esp)
   0x08048b21 <+402>:	call   0x80487cc <_ZNSsD1Ev@plt>
   0x08048b26 <+407>:	jmp    0x8048b57 <main+456>
---Type <return> to continue, or q <return> to quit---
   0x08048b28 <+409>:	mov    %edx,%ebx
   0x08048b2a <+411>:	mov    %eax,%esi
   0x08048b2c <+413>:	lea    0x40(%esp),%eax
   0x08048b30 <+417>:	mov    %eax,(%esp)
   0x08048b33 <+420>:	call   0x80487cc <_ZNSsD1Ev@plt>
   0x08048b38 <+425>:	mov    %esi,%eax
   0x08048b3a <+427>:	mov    %ebx,%edx
   0x08048b3c <+429>:	jmp    0x8048b3e <main+431>
   0x08048b3e <+431>:	mov    %edx,%ebx
   0x08048b40 <+433>:	mov    %eax,%esi
   0x08048b42 <+435>:	lea    0x47(%esp),%eax
   0x08048b46 <+439>:	mov    %eax,(%esp)
   0x08048b49 <+442>:	call   0x804882c <_ZNSaIcED1Ev@plt>
   0x08048b4e <+447>:	mov    %esi,%eax
   0x08048b50 <+449>:	mov    %ebx,%edx
   0x08048b52 <+451>:	jmp    0x8048c26 <main+663>
   0x08048b57 <+456>:	lea    0x47(%esp),%eax
   0x08048b5b <+460>:	mov    %eax,(%esp)
   0x08048b5e <+463>:	call   0x804882c <_ZNSaIcED1Ev@plt>
   0x08048b63 <+468>:	lea    0x4f(%esp),%eax
   0x08048b67 <+472>:	mov    %eax,(%esp)
   0x08048b6a <+475>:	call   0x804887c <_ZNSaIcEC1Ev@plt>
   0x08048b6f <+480>:	mov    0xc(%ebp),%eax
---Type <return> to continue, or q <return> to quit---
   0x08048b72 <+483>:	add    $0x8,%eax
   0x08048b75 <+486>:	mov    (%eax),%eax
   0x08048b77 <+488>:	lea    0x4f(%esp),%edx
   0x08048b7b <+492>:	mov    %edx,0x8(%esp)
   0x08048b7f <+496>:	mov    %eax,0x4(%esp)
   0x08048b83 <+500>:	lea    0x48(%esp),%eax
   0x08048b87 <+504>:	mov    %eax,(%esp)
   0x08048b8a <+507>:	call   0x80487ec <_ZNSsC1EPKcRKSaIcE@plt>
   0x08048b8f <+512>:	lea    0x48(%esp),%eax
   0x08048b93 <+516>:	mov    %eax,0x4(%esp)
   0x08048b97 <+520>:	lea    0x18(%esp),%eax
   0x08048b9b <+524>:	mov    %eax,(%esp)
   0x08048b9e <+527>:	call   0x8048cfc <_ZNSt3mapISsPFiiiESt4lessISsESaISt4pairIKSsS1_EEEixERS5_>
   0x08048ba3 <+532>:	mov    (%eax),%esi
   0x08048ba5 <+534>:	mov    0xc(%ebp),%eax
   0x08048ba8 <+537>:	add    $0xc,%eax
   0x08048bab <+540>:	mov    (%eax),%eax
   0x08048bad <+542>:	mov    %eax,(%esp)
   0x08048bb0 <+545>:	call   0x80487fc <atoi@plt>
   0x08048bb5 <+550>:	mov    %eax,%ebx
   0x08048bb7 <+552>:	mov    0xc(%ebp),%eax
   0x08048bba <+555>:	add    $0x4,%eax
---Type <return> to continue, or q <return> to quit---
   0x08048bbd <+558>:	mov    (%eax),%eax
   0x08048bbf <+560>:	mov    %eax,(%esp)
   0x08048bc2 <+563>:	call   0x80487fc <atoi@plt>
   0x08048bc7 <+568>:	mov    %ebx,0x4(%esp)
   0x08048bcb <+572>:	mov    %eax,(%esp)
   0x08048bce <+575>:	call   *%esi
=> 0x08048bd0 <+577>:	mov    %eax,%ebx
   0x08048bd2 <+579>:	lea    0x48(%esp),%eax
   0x08048bd6 <+583>:	mov    %eax,(%esp)
   0x08048bd9 <+586>:	call   0x80487cc <_ZNSsD1Ev@plt>
   0x08048bde <+591>:	jmp    0x8048c0c <main+637>
   0x08048be0 <+593>:	mov    %edx,%ebx
   0x08048be2 <+595>:	mov    %eax,%esi
   0x08048be4 <+597>:	lea    0x48(%esp),%eax
   0x08048be8 <+601>:	mov    %eax,(%esp)
   0x08048beb <+604>:	call   0x80487cc <_ZNSsD1Ev@plt>
   0x08048bf0 <+609>:	mov    %esi,%eax
   0x08048bf2 <+611>:	mov    %ebx,%edx
   0x08048bf4 <+613>:	jmp    0x8048bf6 <main+615>
   0x08048bf6 <+615>:	mov    %edx,%ebx
   0x08048bf8 <+617>:	mov    %eax,%esi
   0x08048bfa <+619>:	lea    0x4f(%esp),%eax
   0x08048bfe <+623>:	mov    %eax,(%esp)
   0x08048c01 <+626>:	call   0x804882c <_ZNSaIcED1Ev@plt>
   0x08048c06 <+631>:	mov    %esi,%eax
   0x08048c08 <+633>:	mov    %ebx,%edx
   0x08048c0a <+635>:	jmp    0x8048c26 <main+663>
   0x08048c0c <+637>:	lea    0x4f(%esp),%eax
   0x08048c10 <+641>:	mov    %eax,(%esp)
   0x08048c13 <+644>:	call   0x804882c <_ZNSaIcED1Ev@plt>
   0x08048c18 <+649>:	lea    0x18(%esp),%eax
   0x08048c1c <+653>:	mov    %eax,(%esp)
   0x08048c1f <+656>:	call   0x8048c5a <_ZNSt3mapISsPFiiiESt4lessISsESaISt4pairIKSsS1_EEED2Ev>
   0x08048c24 <+661>:	jmp    0x8048c42 <main+691>
   0x08048c26 <+663>:	mov    %edx,%ebx
   0x08048c28 <+665>:	mov    %eax,%esi
   0x08048c2a <+667>:	lea    0x18(%esp),%eax
   0x08048c2e <+671>:	mov    %eax,(%esp)
   0x08048c31 <+674>:	call   0x8048c5a <_ZNSt3mapISsPFiiiESt4lessISsESaISt4pairIKSsS1_EEED2Ev>
   0x08048c36 <+679>:	mov    %esi,%eax
   0x08048c38 <+681>:	mov    %ebx,%edx
   0x08048c3a <+683>:	mov    %eax,(%esp)
   0x08048c3d <+686>:	call   0x804889c <_Unwind_Resume@plt>
   0x08048c42 <+691>:	mov    %ebx,%eax
   0x08048c44 <+693>:	add    $0x58,%esp
   0x08048c47 <+696>:	pop    %ebx
   0x08048c48 <+697>:	pop    %esi
   0x08048c49 <+698>:	mov    %ebp,%esp
   0x08048c4b <+700>:	pop    %ebp
   0x08048c4c <+701>:	ret    
End of assembler dump.

出现coredump可能是因为这一条指令

   0x08048bce <+575>:	call   *%esi

看一下esi的值:

(gdb) i r esi
esi            0x0	0

可见esi为0,确实是由于那一条指令引起的.

那么为什么esi的值是从哪里来的?

   0x08048b8f <+512>:	lea    0x48(%esp),%eax
   0x08048b93 <+516>:	mov    %eax,0x4(%esp)
   0x08048b97 <+520>:	lea    0x18(%esp),%eax
   0x08048b9b <+524>:	mov    %eax,(%esp)
   0x08048b9e <+527>:	call   0x8048cfc <_ZNSt3mapISsPFiiiESt4lessISsESaISt4pairIKSsS1_EEEixERS5_>
   0x08048ba3 <+532>:	mov    (%eax),%esi

可见esi是0x08048b9e处所调用的函数,

_ZNSt3mapISsPFiiiESt4lessISsESaISt4pairIKSsS1_EEEixERS5_的返回值

而_ZNSt3mapISsPFiiiESt4lessISsESaISt4pairIKSsS1_EEEixERS5_的实际名称:

[xuzhina@localhost s3_ex]$ c++filt _ZNSt3mapISsPFiiiESt4lessISsESaISt4pairIKSsS1_EEEixERS5_
std::map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int (*)(int, int), std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int (*)(int, int)> > >::operator[](std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)

由于map的operater[]有一个参数,由上面看,可知map对象的地址是esp+0x18,那个参数是放在esp+0x48,而这个刚好是一个string对象的this指针.见0x08048b8a调用了构造函数

   0x08048b6f <+480>:	mov    0xc(%ebp),%eax
   0x08048b72 <+483>:	add    $0x8,%eax
   0x08048b75 <+486>:	mov    (%eax),%eax
   0x08048b77 <+488>:	lea    0x4f(%esp),%edx
   0x08048b7b <+492>:	mov    %edx,0x8(%esp)
   0x08048b7f <+496>:	mov    %eax,0x4(%esp)
   0x08048b83 <+500>:	lea    0x48(%esp),%eax
   0x08048b87 <+504>:	mov    %eax,(%esp)
   0x08048b8a <+507>:	call   0x80487ec <_ZNSsC1EPKcRKSaIcE@plt>

[xuzhina@localhost s3_ex]$ c++filt _ZNSsC1EPKcRKSaIcE
std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&)

可知,这个string的构造函数只是接收了一个参数,而这个参数是由ebp+c所指向内存地址偏移+8所得来的.

而ebp+0xc是main函数的第二个参数,由main函数的原型

int main( int argc, char* argv[] );

可知

这个参数应该是argv[2],而argv[2]是字符串。它的值是多少呢?

(gdb) x /wx $ebp+0xc
0xbfd3def4:	0xbfd3df94
(gdb) x /8wx 0xbfd3df94
0xbfd3df94:	0xbfd3f543	0xbfd3f55c	0xbfd3f55e	0xbfd3f560
0xbfd3dfa4:	0x00000000	0xbfd3f562	0xbfd3f585	0xbfd3f5a4
(gdb) x /s 0xbfd3f55e
0xbfd3f55e:	 "/"

再看一下map的内容有哪些。由上面已经知道map对象的地址是esp+0x18。且由于上面参数的类型可以知道,这个map对象的key是string类型,而val是函数指针

(gdb) x /8wx $esp+0x18
0xbfd3de98:	0x00000001	0x00000000	0x089a7020	0x089a7090
0xbfd3dea8:	0x089a70c8	0x00000004	0x089a7014	0x0804bb84
(gdb) x /8wx 0x089a7020
0x89a7020:	0x00000001	0xbfd3de9c	0x089a7090	0x089a7058
0x89a7030:	0x089a7014	0x08048964	0x00000000	0x00000019
(gdb) x /8wx 0x089a7014
0x89a7014:	0x0000002b	0x00000000	0x00000021	0x00000001
0x89a7024:	0xbfd3de9c	0x089a7090	0x089a7058	0x089a7014
(gdb) x /s 0x089a7014
0x89a7014:	 "+"
(gdb) info symbol 0x08048964
add(int, int) in section .text of /home/xuzhina/code/s3_ex/xuzhina_dump_c07_s3_ex
(gdb) x /8wx 0x089a7090
0x89a7090:	0x00000001	0x089a7020	0x00000000	0x00000000
0x89a70a0:	0x089a7084	0x08048983	0x00000000	0x00000019
(gdb) x /8wx 0x089a7084
0x89a7084:	0x0000002a	0x00000000	0x00000021	0x00000001
0x89a7094:	0x089a7020	0x00000000	0x00000000	0x089a7084
(gdb) x /s 0x089a7084
0x89a7084:	 "*"
(gdb) info symbol 0x08048983
mul(int, int) in section .text of /home/xuzhina/code/s3_ex/xuzhina_dump_c07_s3_ex
(gdb) x /8wx 0x089a7058
0x89a7058:	0x00000001	0x089a7020	0x00000000	0x089a70c8
0x89a7068:	0x089a704c	0x08048972	0x00000000	0x00000019
(gdb) x /8wx 0x089a704c
0x89a704c:	0x0000002d	0x00000000	0x00000021	0x00000001
0x89a705c:	0x089a7020	0x00000000	0x089a70c8	0x089a704c
(gdb) x /s 0x089a704c
0x89a704c:	 "-"
(gdb) info symbol 0x08048972
sub(int, int) in section .text of /home/xuzhina/code/s3_ex/xuzhina_dump_c07_s3_ex
(gdb) x /8wx 0x089a70c8
0x89a70c8:	0x00000000	0x089a7058	0x00000000	0x00000000
0x89a70d8:	0x089a70bc	0x00000000	0x00000000	0x00020f21
(gdb) x /8wx 0x089a70bc
0x89a70bc:	0x0000002f	0x00000000	0x00000021	0x00000000
0x89a70cc:	0x089a7058	0x00000000	0x00000000	0x089a70bc
(gdb) x /s 0x089a70bc
0x89a70bc:	 "/"


而main函数调用_ZNSt3mapISsPFiiiESt4lessISsESaISt4pairIKSsS1_EEEixERS5_除了coredump的附近之外,还有三处调用了。

   0x080489ea <+91>:	lea    0x30(%esp),%eax
   0x080489ee <+95>:	mov    %eax,0x4(%esp)
   0x080489f2 <+99>:	lea    0x18(%esp),%eax
   0x080489f6 <+103>:	mov    %eax,(%esp)
   0x080489f9 <+106>:	call   0x8048cfc <_ZNSt3mapISsPFiiiESt4lessISsESaISt4pairIKSsS1_EEEixERS5_>
   0x080489fe <+111>:	movl   $0x8048964,(%eax)  

 0x08048a75 <+230>:	lea    0x38(%esp),%eax
   0x08048a79 <+234>:	mov    %eax,0x4(%esp)
   0x08048a7d <+238>:	lea    0x18(%esp),%eax
   0x08048a81 <+242>:	mov    %eax,(%esp)
---Type <return> to continue, or q <return> to quit---
   0x08048a84 <+245>:	call   0x8048cfc <_ZNSt3mapISsPFiiiESt4lessISsESaISt4pairIKSsS1_EEEixERS5_>
   0x08048a89 <+250>:	movl   $0x8048972,(%eax)

   0x08048b00 <+369>:	lea    0x40(%esp),%eax
   0x08048b04 <+373>:	mov    %eax,0x4(%esp)
   0x08048b08 <+377>:	lea    0x18(%esp),%eax
   0x08048b0c <+381>:	mov    %eax,(%esp)
   0x08048b0f <+384>:	call   0x8048cfc <_ZNSt3mapISsPFiiiESt4lessISsESaISt4pairIKSsS1_EEEixERS5_>
   0x08048b14 <+389>:	movl   $0x8048983,(%eax)


其中0x8048964,0x8048972,0x8048983正好是那三个函数指针。可见,main函数并没有往map对象里面放入”/”的val。

 

看一下程序代码,

  1 #include <map>
  2 #include <string>
  3 #include <stdio.h>
  4 #include <stdlib.h>
  5 
  6 typedef int (*oper)(int a, int b );
  7 
  8 int add( int a, int b )
  9 {
 10     return a + b;
 11 }
 12 
 13 int sub( int a, int b )
 14 {
 15     return a - b;
 16 }
 17 
 18 int mul( int a, int b )
 19 {
 20     return a * b;
 21 }
 22 
 23 int main( int argc, char* argv[] )
 24 {
 25     if ( argc < 4 )
 26     {
 27         printf( "parameter less than 4\n" );
 28         return -1;
 29     }
 30 
 31     std::map< std::string, oper> operMap;
 32     operMap["+"] = &add;
 33     operMap["-"] = ?
 34     operMap["*"] = &mul;
 35 
 36     return operMap[argv[2]]( atoi( argv[1] ), atoi( argv[3] ) );
 37 }

 

可知,确实如上面所分析那样.所以,对于获取map里面的元素,用operator[]要慎重.


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。