Destructor 调用究竟是如何进行的

How exactly are Destructor calls made

我想知道在 C++ 中,构造函数或析构函数究竟是如何被调用的?我对 OS 观点特别感兴趣。我也对我们 运行 android 用 java 编写的应用程序的情况感兴趣,我们想要获取有关用户会话的信息。我们可以使用 conatructor 设置会话开始时间和 destr 设置会话结束时间并将数据保存在数据库中吗?实际上 OS 是否处理析构函数调用或其他?提前致谢!

我不熟悉Java如何处理构造函数和析构函数(Java涉及虚拟机层),但我会尝试从cpp的角度回答这个问题。

对你的问题的简短回答:OS不参与构造函数或析构函数(除非有堆分配、系统调用...)。编译器在生成机器码时会在正确的位置插入对构造函数和析构函数的调用。

简单程序如下:

class A{

    int* i;
public:
    A() { i = new int; }
    ~A() { delete i; }
};

int main() {
    A a;
}

让我们检查一下编译器使用 objdump:

发出的汇编代码
00000000004006a6 <main>:
  4006a6:       55                      push   %rbp
  4006a7:       48 89 e5                mov    %rsp,%rbp
  4006aa:       48 83 ec 10             sub    [=11=]x10,%rsp
  4006ae:       64 48 8b 04 25 28 00    mov    %fs:0x28,%rax
  4006b5:       00 00 
  4006b7:       48 89 45 f8             mov    %rax,-0x8(%rbp)
  4006bb:       31 c0                   xor    %eax,%eax
  4006bd:       48 8d 45 f0             lea    -0x10(%rbp),%rax
  4006c1:       48 89 c7                mov    %rax,%rdi
  4006c4:       e8 27 00 00 00          callq  4006f0 <_ZN1AC1Ev>
  4006c9:       48 8d 45 f0             lea    -0x10(%rbp),%rax
  4006cd:       48 89 c7                mov    %rax,%rdi
  4006d0:       e8 3f 00 00 00          callq  400714 <_ZN1AD1Ev>
  4006d5:       b8 00 00 00 00          mov    [=11=]x0,%eax
  4006da:       48 8b 55 f8             mov    -0x8(%rbp),%rdx
  4006de:       64 48 33 14 25 28 00    xor    %fs:0x28,%rdx
  4006e5:       00 00 
  4006e7:       74 05                   je     4006ee <main+0x48>
  4006e9:       e8 92 fe ff ff          callq  400580 <__stack_chk_fail@plt>
  4006ee:       c9                      leaveq 
  4006ef:       c3                      retq

请注意,根据底层架构和编译器,您的输出可能与我的不同,但结构通常应该相同。

您可以看到编译器自动生成对构造函数 callq 400714 <_ZN1AD1Ev> 和析构函数 callq 400714 <_ZN1AD1Ev> 的调用。构造函数的汇编代码是:

00000000004006f0 <_ZN1AC1Ev>:
  4006f0:       55                      push   %rbp
  4006f1:       48 89 e5                mov    %rsp,%rbp
  4006f4:       48 83 ec 10             sub    [=12=]x10,%rsp
  4006f8:       48 89 7d f8             mov    %rdi,-0x8(%rbp)
  4006fc:       bf 04 00 00 00          mov    [=12=]x4,%edi
  400701:       e8 8a fe ff ff          callq  400590 <_Znwm@plt>
  400706:       48 89 c2                mov    %rax,%rdx
  400709:       48 8b 45 f8             mov    -0x8(%rbp),%rax
  40070d:       48 89 10                mov    %rdx,(%rax)
  400710:       90                      nop
  400711:       c9                      leaveq 
  400712:       c3                      retq   
  400713:       90                      nop

析构函数的程序集:

0000000000400714 <_ZN1AD1Ev>:
  400714:       55                      push   %rbp
  400715:       48 89 e5                mov    %rsp,%rbp
  400718:       48 83 ec 10             sub    [=13=]x10,%rsp
  40071c:       48 89 7d f8             mov    %rdi,-0x8(%rbp)
  400720:       48 8b 45 f8             mov    -0x8(%rbp),%rax
  400724:       48 8b 00                mov    (%rax),%rax
  400727:       48 89 c7                mov    %rax,%rdi
  40072a:       e8 31 fe ff ff          callq  400560 <_ZdlPv@plt>
  40072f:       90                      nop
  400730:       c9                      leaveq 
  400731:       c3                      retq   
  400732:       66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
  400739:       00 00 00 
  40073c:       0f 1f 40 00             nopl   0x0(%rax)