C++ summary 工具 Insights: 源码工具:应用篇 inline函数

2023-12-17 20:11:37
  • 介绍篇

  • 在线执行
    在这里插入图片描述

  • 悬停,显示帮助
    在这里插入图片描述

  • 右键,查看文档
    在这里插入图片描述

在这里插入图片描述

  • template
    在这里插入图片描述

example_1

int main(){
    int a = 123;
    return 0;
}
(gdb) disas
Dump of assembler code for function main():
   0x0000555555555129 <+0>:	endbr64 
   0x000055555555512d <+4>:	push   %rbp
   0x000055555555512e <+5>:	mov    %rsp,%rbp
=> 0x0000555555555131 <+8>:	movl   $0x7b,-0x4(%rbp)
   0x0000555555555138 <+15>:	mov    $0x0,%eax
   0x000055555555513d <+20>:	pop    %rbp
   0x000055555555513e <+21>:	ret    
End of assembler dump.
main:
        push    rbp
        mov     rbp, rsp
        mov     DWORD PTR [rbp-4], 123
        mov     eax, 0
        pop     rbp
        ret

example_2

int main(){
    static int a = 123;
    return 0;
}
(gdb) disas
Dump of assembler code for function main():
   0x0000555555555129 <+0>:	endbr64 
   0x000055555555512d <+4>:	push   %rbp
   0x000055555555512e <+5>:	mov    %rsp,%rbp
=> 0x0000555555555131 <+8>:	mov    $0x0,%eax
   0x0000555555555136 <+13>:	pop    %rbp
   0x0000555555555137 <+14>:	ret    
End of assembler dump.
main:
        push    rbp
        mov     rbp, rsp
        mov     eax, 0
        pop     rbp
        ret

example_3

int main(){
    const int a = 123;
    return 0;
}
(gdb) disas
Dump of assembler code for function main():
   0x0000555555555129 <+0>:	endbr64 
   0x000055555555512d <+4>:	push   %rbp
   0x000055555555512e <+5>:	mov    %rsp,%rbp
=> 0x0000555555555131 <+8>:	movl   $0x7b,-0x4(%rbp)
   0x0000555555555138 <+15>:	mov    $0x0,%eax
   0x000055555555513d <+20>:	pop    %rbp
   0x000055555555513e <+21>:	ret    
End of assembler dump.
main:
        push    rbp
        mov     rbp, rsp
        mov     DWORD PTR [rbp-4], 123
        mov     eax, 0
        pop     rbp
        ret

inline函数

在这里插入图片描述
使用 inline 关键字可以对函数进行内联展开(inline expansion),这意味着函数的代码会被直接插入调用它的地方,而不是通过函数调用的方式执行。inline 在编译器的编译阶段被处理)(需要注意的是,inline 仅仅是对编译器的一个提示,编译器完全有权决定是否内联展开函数。它可能会忽略 inline 提示,特别是在一些情况下,如递归函数、虚函数、函数体过大等情况)。使用 inline 可以有以下优点和缺点:

优点:

  1. 提高执行速度:内联展开可以消除函数调用的开销,因为不需要在运行时跳转到函数的位置执行代码。这可以在一定程度上提高程序的执行速度,尤其是对于短小的函数。
  2. 节省函数调用栈:函数调用会在运行时创建调用栈,包含函数参数和返回地址等信息。内联展开可以避免创建和销毁调用栈,从而减少了一部分内存开销,并且可以提高程序的效率。
  3. 编译器优化:内联函数通常会被编译器视为宏替换,使编译器有更多的优化机会,如常量替换、循环展开等。这可以进一步提高程序的性能。

缺点:

  1. 增加代码尺寸:内联展开会导致函数的代码被复制到多个调用点,增加了可执行文件的尺寸。对于一些较大的函数,这可能会增大可执行文件的大小,从而降低缓存效率。
  2. 增加编译时间:内联函数的代码会在每个调用点都进行复制和插入,这可能导致编译时间的增加,特别是当内联函数被频繁调用时。
  3. 可读性和维护性下降:内联函数的代码被复制到多个地方,可能会导致代码重复,并且使代码变得分散。这可能会降低代码的可读性和维护性,特别是在需要对函数进行修改或调试时。

综上所述,使用 inline 可以提高程序的执行效率和编译器的优化机会。然而,应该谨慎使用 inline,并根据函数的大小、调用频率以及代码的可读性和维护性需求来权衡其优缺点。对于短小的、频繁调用且性能关键的函数,使用 inline 可能是合适的选择。

cg

rax rsp是什么

rax(全名为 Accumulator register)是通用目的寄存器之一。在64位模式下,rax 是一个64位寄存器,可以用于存储和操作64位的数据。rax 在函数调用中常用于存储函数返回值。

rsp(全名为 Stack Pointer register)是栈指针寄存器,它指向当前栈的顶部。栈是一块特殊的内存区域,用于存储函数调用过程中的局部变量、函数参数和返回地址等。rsp 的值会随着函数的调用和返回而不断变化,用于管理栈帧的创建和销毁。

  • sub rsp, 0x10: 这条指令将栈指针 rsp 减去一个常数值 0x10,即在栈上分配 16 字节的空间。这通常用于为函数调用准备局部变量或保存临时数据。

  • lea rax, [rsp+0xf]: 这条指令使用地址计算,即将 rsp 寄存器的值加上常数 0xf,结果存储在 rax 寄存器中。这样做的目的是获得 rsp 寄存器向上对齐到 16 字节边界的地址。(lea destination, source, destination 是目标寄存器,用于存储计算得到的地址,source 则表示源操作数,可以是一个内存地址、寄存器或立即数)

  • and rax, 0xfffffffffffffff0: 这条指令将 rax 寄存器的值与常数 0xfffffffffffffff0 进行按位与操作,将 rax 的低 4 位清零,得到一个 16 字节对齐的地址。

  • mov QWORD PTR [rdi], rax: 这条指令将 rax 的值存储到以 rdi 寄存器作为地址的内存位置,即将 rax 的值存储到 rdi 指向的内存中。

从内存中读取 rsp+0x8 地址处的一个 64 位值,然后检查这个值是否为零。根据比较结果,当这个值不为零时,跳转到地址 401145 继续执行后续的指令。

  1. mov rax, QWORD PTR [rsp+0x8]: 这条指令将 rsp 寄存器的值加上偏移量 0x8,然后将结果作为地址,从内存中读取一个 8 字节(64位)的值,并将其存储到 rax 寄存器中。这样做的目的是获取 rsp+0x8 地址处存储的数据。

  2. cmp BYTE PTR [rax], 0x0: 这条指令将 rax 寄存器的值作为地址,从内存中读取一个字节(8位)的值,与常数 0x0 进行比较。这里的目的是检查 rax 寄存器指向的内存位置中的值是否为零(空字节)。

  3. jne 401145 <main+0x85>: 这条指令根据上一条 cmp 指令的结果,当比较结果为不相等(即不为零)时,跳转到地址 401145 处执行。这里是根据条件执行的跳转,当前偏移量 0x85 是相对于当前指令的偏移地址。

文章来源:https://blog.csdn.net/ResumeProject/article/details/132789435
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。