常用命令
1 | tmux new -t $NAME |
Useful to copy
<prefix> + maximizes the current pane to a new window
源码安装
依赖
1 | sudo yum install -y \ |
运行
1 | git clone https://github.com/tmux/tmux.git |
1 | tmux new -t $NAME |
<prefix> + maximizes the current pane to a new window
1 | sudo yum install -y \ |
1 | git clone https://github.com/tmux/tmux.git |
GCC Compiler Option 2 : Preprocessor Options
-M option is designed for auto-generate Makefile rules from g++ command.-E option to STOP after preprocessor during the compilation-w option to DISABLE/suppress all warnings.Using a complex g++ command as an example:
1 | g++ -Wall -Werror -Wno-unknown-pragmas -DPIN_CRT=1 -fno-stack-protector -fno-exceptions -funwind-tables -fasynchronous-unwind-tables -fno-rtti -DTARGET_IA32E -DHOST_IA32E -fPIC -DTARGET_LINUX -fabi-version=2 -faligned-new -I../../../source/include/pin -I../../../source/include/pin/gen -isystem /staff/shaojiemike/Download/pin-3.28-98749-g6643ecee5-gcc-linux/extras/cxx/include -isystem /staff/shaojiemike/Download/pin-3.28-98749-g6643ecee5-gcc-linux/extras/crt/include -isystem /staff/shaojiemike/Download/pin-3.28-98749-g6643ecee5-gcc-linux/extras/crt/include/arch-x86_64 -isystem /staff/shaojiemike/Download/pin-3.28-98749-g6643ecee5-gcc-linux/extras/crt/include/kernel/uapi -isystem /staff/shaojiemike/Download/pin-3.28-98749-g6643ecee5-gcc-linux/extras/crt/include/kernel/uapi/asm-x86 -I../../../extras/components/include -I../../../extras/xed-intel64/include/xed -I../../../source/tools/Utils -I../../../source/tools/InstLib -O3 -fomit-frame-pointer -fno-strict-aliasing -Wno-dangling-pointer |
In Makefile_bk
1 | inscount0.o: inscount0.cpp \ |
-MM not include sys header file-MF filename config the Makefile rules write to which file instead of to stdout.-M -MG is designed to generate Makefile rules when there is header file missing, treated it as generated in normal.-M -MP will generated M-rules for dependency between header filesheader1.h includes header2.h. So header1.h: header2.h in Makefile-MD == -M -MF file without default option -Efile has a suffix of .d, e.g., inscount0.d for -c inscount0.cpp-MMD == -MD not include sys header file暂无
暂无
上面回答部分来自ChatGPT-3.5,没有进行正确性的交叉校验。
无
Pin 是一个动态二进制插桩工具:

Pin机制类似Just-In-Time (JIT) 编译器,Trace插桩的基本流程(以动态基本块BBLs为分析单位):
通过一个例子来说明动态基本块BBLs与 汇编代码的BB的区别
1 | switch(i) |
上述代码会编译成下面的汇编, 对于实际执行时跳转从.L7进入的情况,BBLs包括四条指令,但是BB只会包括一条。
1 | .L7: |
Pin会将cpuid, popf and REP prefixed 指令在执行break 成很多BBLs,导致执行的基本块比预想的要多。(主要原因是这些指令有隐式循环,所以Pin会将其拆分成多个BBLs)
kit from Intel websiteThis part is always needed by pintool, for example Zsim, Sniper.
When you meet the following situation, you should consider update your pin version even you can ignore this warning by use flags like -ifeellucky under high compatibility risk.
1 | shaojiemike@snode6 ~/github/ramulator-pim/zsim-ramulator/pin [08:05:47] |
because this will easily lead to the problem
1 | Pin app terminated abnormally due to signal 6. # or signal 4. |
PIN_Init之前调用PIN_InitSymbols。1 | for (SEC sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec)) |
最重要的是
TRACE_AddInstrumentFunction Add a function used to instrument at trace granularityINS_AddInstrumentFunction() Add a function used to instrument at instruction granularityIMG_AddInstrumentFunction() Use this to register a call back to catch the loading of an imageINS_InsertPredicatedCall()1 | // Forward pass over all instructions in bbl |
1 | // Visit every basic block in the trace |
1 | UINT32 memOperands = INS_MemoryOperandCount(ins); |
最重要的是
示例分析
1 | // IPOINT_BEFORE 时运行的分析函数 |
目标:以样例插桩工具的源码为对象,熟悉pin的debug流程。
以官方教程为例子:
1 | uname -a #intel64 |
测试运行
1 | ../../../pin -t obj-intel64/inscount0.so -- ./a.out #正常统计指令数 to inscount.out |
下面介绍Pin 提供的debug工具:
首先创建所需的-g的stack-debugger.so和应用fibonacci.exe
1 | cd source/tools/ManualExamples |
其中OPT=-O0选项来自官方文档Using Fast Call Linkages小节,说明需要OPT=-O0选项来屏蔽makefile中的-fomit-frame-pointer选项,使得GDB能正常显示stack trace(函数堆栈?)
1 | $ ../../../pin -appdebug -t obj-intel64/stack-debugger.so -- obj-intel64/fibonacci.exe 1000 |
使用pin的-appdebug选项,在程序第一条指令前暂停,并启动debugger窗口。在另一个窗口里gdb通过pid连接:
1 | $ gdb fibonacci #如果没指定应用obj-intel64/fibonacci.exe |
能够在上一小节的debug窗口里,通过自定义debug指令打印自定义程序相关信息(比如当前stack使用大小)
Pintool “stack-debugger” 能够监控每条分配stack空间的指令,并当stack使用达到阈值时stop at a breakpoint。
这功能由两部分代码实现,一个是插桩代码,一个是分析代码。
1 | static VOID Instruction(INS ins, VOID *) |
所需的两个函数的分析代码如下:
1 | static ADDRINT OnStackChangeIf(ADDRINT sp, ADDRINT addrInfo) |
OnStackChangeIf函数监控当前的stack使用并判断是否到达阈值。DoBreakpoint函数连接debugger窗口,然后触发breakpoint,并打印相关信息。
也可以使用-appdebug_enable参数,取消在第一条指令前开启GDB窗口的功能,而是在触发如上代码的break时,才开启GDB窗口的连接。
而上述代码中的ConnectDebugger函数实现如下:
1 | static void ConnectDebugger() |
这部分讲述了如何debug Pintool中的问题。(对Pintool的原理也能更了解
为此,pin使用了-pause_tool n 暂停n秒等待gdb连接。
1 | ../../../pin -pause_tool 10 -t /staff/shaojiemike/github/sniper_PIMProf/pin_kit/source/tools/ManualExamples/obj-intel64/stack-debugger.so -- obj-intel64/fibonacci.exe 1000 |
注意gdb对象既不是pin也不是stack-debugger.so,而是intel64/bin/pinbin。原因是intel64/bin/pinbin是pin执行时的核心程序,通过htop监控可以看出。
1 | # shaojiemike @ snode6 in ~/github/sniper_PIMProf/pin_kit/source/tools/ManualExamples on git:dev x [19:57:26] |
这时GDB缺少了stack-debugger.so的调试信息,需要手动添加。这里的add-symbol-file命令是在pin启动时打印出来的,直接复制粘贴即可。
1 | (gdb) add-symbol-file /staff/shaojiemike/github/sniper_PIMProf/pin_kit/source/tools/ManualExamples/obj-intel64/stack-debugger.so 0x7f3105f24170 -s .data 0x7f31061288a0 -s .bss 0x7f3106129280 |
stack-debugger.so的调试信息,无法设置断点。暂无
暂无
Zsim模拟器是
awesome-shell里多看看。
rg (Fast & Good multi-platform compatibility) > ag > ack(ack-grep) 🔥
1 | # 当前文件夹下查找 dlog关键字 |
find . -name "*xxx*"
lazydocker
The default program entry function is main, but can be changed in two situations:
#define xxx main in header file to replace the name which maybe ignored by silly search bar in VSCODE.-exxx compile flag;)取决于上下文。if, while, for)、复合语句({}) 不需要分号。#define, #include):不需要分号,因为它们不是 C++ 语法层面的内容。} 不需要分号,但声明类或结构体时 } 后要加分号。总结来说,分号用来结束语句,包括声明、表达式和执行体等,但当你定义一个复合结构(如函数定义、控制语句)时,不需要分号来结束复合结构的定义。
1 | int getKthAncestor(int node, int k) { |
根据C++的作用域规则,内层的局部变量会覆盖外层的同名变量。因此,在第二行的语句中,node引用的是函数参数中的node,而不是你想要的之前定义的node。
为了避免这个问题,你可以修改代码,避免重复定义变量名。例如,可以将第二行的变量名改为newNode或其他不同的名称,以避免与函数参数名冲突。
运算符性质:
https://en.cppreference.com/w/cpp/language/types
https://en.cppreference.com/w/cpp/types/integer
1 | //返回与平台相关的数值类型的极值 |
1 | extern |
static 作⽤:控制变量的存储⽅式和作用范围(可⻅性)。
int MyClass::staticVariable = 10;当const修饰基本数据类型时,可以将其放置在类型说明符的前面或后面,效果是一样的。const关键字用于声明一个常量,即其值在声明后不可修改。
1 | const int constantValue1 = 10; // const在类型说明符前 |
当const关键字位于指针变量或引用变量的左侧时,它用于修饰指针所指向的变量,即指针指向的内容为常量。当const关键字位于指针变量或引用变量的右侧时,它用于修饰指针或引用本身,即指针或引用本身是常量。
修饰指针指向的变量, 它指向的值不能修改:
1 | int x = 5; |
修饰指针本身 ,它不能再指向别的变量,但指向(变量)的值可以修改。:
1 | const int y = 10; |
const int *const p3; //指向整形常量 的 常量指针 。它既不能再指向别的常量,指向的值也不能修改。
在C++, explicit 是一个关键字,用于修饰单参数构造函数,用于禁止隐式类型转换。
当一个构造函数被声明为 explicit 时,它指示编译器在使用该构造函数进行类型转换时只能使用显式调用,而不允许隐式的类型转换发生。
通过使用 explicit 关键字,可以防止一些意外的类型转换,提高代码的清晰性和安全性。它通常用于防止不必要的类型转换,特别是在单参数构造函数可能引起歧义或产生意外结果的情况下。
#include_next 的作用是b.cpp想使用stdlib.h, 那么在代码的目录下创建stdlib.h,并在该文件里#include_next "stdlib.h" 防止递归引用。#define PI 3.14159,在代码中将PI替换为3.14159。const:
const int MAX_VALUE = 100;,声明一个名为MAX_VALUE的常量。typedef:
typedef int Age;,为int类型创建了一个别名Age。inline:
inline int add(int a, int b) { return a + b; },声明了一个内联函数add。define主要用于宏定义,const用于声明常量,typedef用于创建类型别名,inline用于内联函数的声明。
为了避免同一个文件被include多次,C/C++中有两种方式,一种是#ifndef方式,一种是#pragma once方式。在能够支持这两种方式的编译器上,二者并没有太大的区别,但是两者仍然还是有一些细微的区别。
1 |
|
namespace 会影响 typedef 的作用范围,但不会直接限制 #define 宏的作用范围。
1 | //值传递 |
引用传递和指针传递的区别:
指针传递和引用传递的使用情景:
虽然理论上可以通过类似void f(bool x = true)来实现默认值。
1 | // 函数声明 |

1 | template<typename T> |
1 |
|
VA_LIST 是在C语言中解决变参问题的一组宏,变参问题是指参数的个数不定,可以是传入一个参数也可以是多个;可变参数中的每个参数的类型可以不同,也可以相同;可变参数的每个参数并没有实际的名称与之相对应,用起来是很灵活。
系统提供了vprintf系列格式化字符串的函数,用于编程人员封装自己的I/O函数。
1 | int vprintf / vscanf (const char * format, va_list ap); // 从标准输入/输出格式化字符串 |
使用结构体
1 | struct RowAndCol { int row;int col; }; |
在 C++ 中,左值(lvalue) 和 右值(rvalue) 是两个重要的概念,用来描述表达式的值和内存的关系。它们帮助开发者理解变量的生命周期、赋值和对象管理,特别是在现代 C++ 中引入了右值引用后,优化了移动语义和资源管理。
左值(lvalue,locatable value) 是指在内存中有明确地址、可持久存在的对象,可以对其进行赋值操作。通俗地说,左值是能够取地址的值,可以出现在赋值操作符的左边。
特点:
& 运算符)。右值(rvalue,readable value) 是没有明确地址、临时存在的对象,不能对其进行赋值操作。它们通常是字面值常量或表达式的结果。右值只能出现在赋值操作符的右边,表示一个临时对象或数据。
特点:
& 获取右值的地址)。C++11 引入了 右值引用,即通过 && 符号表示。这使得右值也能通过引用进行操作,特别是在实现移动语义(move semantics)和避免不必要的拷贝时非常有用。右值引用允许我们通过右值管理资源,避免性能上的损失。
通常,左值是表示持久存在的对象,可以通过取地址符 & 获取其地址,而右值是临时的、短暂存在的值,不能直接获取其地址。理解这两者对于编写高效的 C++ 代码和使用现代特性(如右值引用和移动语义)非常重要。
&&)是 C++11 引入的新特性,用来优化资源管理和避免不必要的拷贝操作。在C++98/03中我们只能对普通数组和POD(plain old data,简单来说就是可以用memcpy复制的对象)类型可以使用列表初始化,如下:
1 | //数组的初始化列表: |
在C++11中初始化列表被适用性被放大,可以作用于任何类型对象的初始化。如下:
1 | X x1 = X{1,2}; |
聚合类型可以进行直接列表初始化
聚合类型包括
对于一个聚合类型,使用列表初始化相当于使用std::initializer_list对其中的相同类型T的每个元素分别赋值处理,类似下面示例代码;
1 | struct CustomVec { |
⼩贺 C++ ⼋股⽂ PDF 的作者,电⼦书的内容整理于公众号「herongwei」
https://shaojiemike.notion.site/C-11-a94be53ca5a94d34b8c6972339e7538a
暂无
暂无
上面回答部分来自ChatGPT-3.5,没有进行正确性的交叉校验。
无