
本文不是让你成为c/c++专家, 而是让你成为c/c+面试专家

程序调试:添加打印log日志方式 确实一个很好方式 但是 一个大型项目,修改一行代码,编译1个小时,开发自测阶段 这个不是浪费你宝贵时间呀?因此必须了解gdb调试最基本技巧
任务:使用gdb 方式直接运行一个服务 带参数服务
使用 gdb --args 前缀,将程序路径和所有参数一起传入,确保参数被正确识别。
gdb --args ./test -N 4 -c x
先进入 GDB 调试环境,再通过 set args 命令设置参数,最后用 run 运行。
1
启动 GDB 并加载程序:
gdb ./test2
在 GDB 内部设置参数:
(gdb) set args -N 4 -c x3
设置断点
(gdb) rungit fetch origin
•
git fetch是将远程主机的最新内容拉到本地,用户在检查了以后决定是否合并到工作本机分支中。
•
git pull 则是将远程主机的最新内容拉下来后直接合并,
即:git pull = git fetch + git merge,这样可能会产生冲突,需要手动解决。
git merge origin branch_wangchuanyi
git-merge - Join two or more development histories together
A---B---C topic
/
D---E---F---G master
A---B---C topic
/ \
D---E---F---G---H master
创建本地分支
git checkout -b branch_wangchuanyi origin/money/branch_wangchuanyi
git push origin branch_wangchuanyi:money/branch_wangchuanyi
how-to-push-a-local-branch-to-a-remote-repository-in-git
•
git add -u
•
git clean -dfx
git clean -dfx -d:删除未跟踪的目录 -f:强制删除(force) -x:删除所有未跟踪的文件,包括被.gitignore忽略的文件

同一个RPC消息, 消息类型没有发生变化,消息结构没有发生变化,为什么?最后sizeof 计算类大小不一样呢?
取消所有填充字节,结构体大小 = 所有成员大小之和(最紧凑)// 强制按1字节对齐(无填充字节) #pragma pack(1) struct Test { char a; // 1字节 int b; // 4字节(紧跟a,无填充) }; #pragma pack() // 恢复默认对齐 // 大小:1+4=5字节(默认对齐下是8字节:1+3填充+4)高端开源 RPC 框架(gRPC、Protobuf)彻底不用「结构体内存镜像传输」,
而是通过 IDL 文件(如.proto)定义消息,编译后生成序列化 / 反序列化代码
—— 此时sizeof无关紧要,传输的是 “编码后的字节流”,完全规避对齐差异。
疑问:IDL + 序列化 和直接序列化区别是什么?
你之前遇到的「结构体 sizeof 不一致、对齐差异」,本质是因为 RPC 消息传输用了「直接拷贝结构体在内存中的原样」(也就是「内存镜像」),这个过程就像:
把你房间里的家具(结构体成员)原样搬到另一个房子(目标平台),家具之间的间隙(编译器插入的填充字节)、摆放位置(对齐规则)完全依赖房子的户型(编译器/平台)—— 户型变了(比如 MSVC 换成 GCC),间隙大小就变,家具占的总空间(sizeof)也变,搬过去就会乱套。
举个具体例子:
你定义了一个 RPC 消息结构体:
struct UserMsg { char name; // 1字节 int age; // 4字节};•
在 GCC 下,编译器会在 name 后插 3 字节填充(对齐要求),sizeof(UserMsg)=8;
•
在 MSVC 下,若开了 pack(4),可能只插 0 字节填充,sizeof(UserMsg)=5;
如果直接把这个结构体的「内存镜像」(8 字节/5 字节)通过网络传给对方,对方按自己的 sizeof 解析,就会把填充字节当成有效数据,导致解析错误(比如 age 读成乱码)。
gRPC/Protobuf 这类框架的思路是:不直接传内存里的结构体,而是先把结构体的「数据值」按「统一规则」拆成纯字节流(序列化),接收方再按同一规则还原(反序列化)。
这个过程就像:
把房间里的家具(结构体成员)拆成标准化零件(只保留有效数据,去掉所有填充字节),按「组装清单」(IDL 定义的规则)打包成快递(字节流);接收方收到快递后,按同一清单把零件组装成家具—— 不管接收方的房子(编译器/平台)户型如何,只要清单一致,组装出的家具(数据)就完全一样,和“间隙(填充)”“户型(对齐)”无关。
我们用 Protobuf 举一个最简化的例子,你就能直观理解:
创建 user_msg.proto 文件,只定义「数据是什么、是什么类型」,完全不涉及内存布局:
// 版本声明syntax = "proto3";// 定义消息(对应你的结构体)message UserMsg { string name = 1; // 字段1:字符串类型(对应char name) int32 age = 2; // 字段2:32位整数(对应int age)}这个文件就是「跨平台/编译器的统一规则」—— 不管是 MSVC、GCC 还是 Clang,不管是 32 位还是 64 位,所有人都按这个清单来处理数据。
用 Protobuf 编译器 protoc 把 .proto 文件编译成你需要的语言代码(C++/Java/Go 等):
# 编译成C++代码protoc --cpp_out=. user_msg.proto编译后会生成 user_msg.pb.h 和 user_msg.pb.cc,里面包含:
•
对应 UserMsg 的类(替代你手写的结构体);
•
自动生成的 SerializeToString()(序列化)、ParseFromString()(反序列化)函数。
发送方代码(不管什么编译器,逻辑都一样):
// 1. 创建消息对象,赋值(只关心数据值,不关心内存布局)UserMsg msg;msg.set_name("Tom"); // 设值:字符串msg.set_age(20); // 设值:整数// 2. 序列化:把数据转成纯字节流(无任何填充字节)std::string byte_stream;msg.SerializeToString(&byte_stream);// 3. 传输字节流(RPC框架负责把byte_stream发出去)rpc_client.Send(byte_stream);这个 byte_stream 里只有「Tom」和「20」的有效数据,没有任何编译器插入的填充字节,大小完全由数据本身决定,和 sizeof、对齐规则无关。
接收方代码(不管什么编译器,逻辑都一样):
// 1. 接收字节流std::string received_byte_stream = rpc_server.Receive();// 2. 反序列化:按.proto规则还原数据UserMsg msg;msg.ParseFromString(received_byte_stream);// 3. 读取数据(结果和发送方完全一致)std::cout << msg.name() << ", " << msg.age() << std::endl;// 输出:Tom, 20核心原因就3点,也是开源 RPC 框架选择这种方案的本质:
1
只传输「数据值」,不传输「内存布局」:序列化后的字节流只包含有效数据(比如字符、数字),完全剔除了编译器插入的填充字节,自然不存在「填充多少、对齐规则」的差异;
2
IDL 保证「规则统一」:.proto 文件是跨编译器/平台的“统一契约”,不管发送方用 MSVC、接收方用 GCC,都按同一个规则解析数据,和 #pragma pack、sizeof 无关;
3
编译生成的代码「适配底层」:Protobuf 自动生成的序列化/反序列化代码,已经帮你处理了所有编译器/平台的细节差异(比如大小端、类型长度),你不用关心底层。
传统方式(内存镜像) | 序列化解耦(Protobuf/gRPC) |
|---|---|
传输「内存里的结构体原样」,包含填充字节 | 传输「纯有效数据的字节流」,无填充 |
依赖编译器对齐规则、sizeof | 只依赖IDL定义的统一规则 |
不同编译器/平台易出解析错误 | 跨平台/编译器100%兼容 |
有没有一份跨语言、跨平台的“公共契约”。
•
直接序列化: 你用母语写了一份便签(内存对象),然后用自己发明的符号加密成一段文字(字节流),对方只有也是说母语、懂你加密规则的人才能读懂。 → 只能在同一语言/同一运行时环境内使用。
•
IDL + 序列化: 你和对方先约定用“世界语”写合同(IDL 文件),然后把合同内容翻译成各国语言(生成各语言的代码),通信时双方都按合同拆装箱(序列化/反序列化)。 → 跨语言、跨平台、长期演进无压力。
维度 | 直接序列化 | IDL + 序列化 |
|---|---|---|
跨语言能力 | ❌ 几乎不行(如 Java 的 Serializable 只能 Java 反序列化) | ✅ 天生支持(Protobuf/Thrift 等可生成 Java/C++/Go/Python…) |
跨平台/编译器 | ❌ 依赖内存布局,对齐/大小端差异易出错 | ✅ 二进制格式固定,与平台/编译器完全无关 |
版本兼容性 | ❌ 字段增删几乎必挂(新旧版本不兼容) | ✅ 通过字段编号/optional 设计,向后向前兼容 |
契约文档 | ❌ 无显式契约,反序列化靠硬编码 | ✅ .proto 文件即是契约,可读、可校验、可生成文档 |
性能 | ⚠️ 依赖反射,通常较慢(如 Java 反射、Python pickle) | ✅ 代码生成,零反射/少反射,常带 Varint 等优化 |
安全风险 | ⚠️ 反序列化可能执行任意代码(如 Java 反序列化漏洞) | ✅ 只解析已知字段,天然防御大部分反序列化攻击 |
数据体积 | ⚠️ 常包含类型元数据、类结构信息,臃肿 | ✅ 仅存编号+值,紧凑(尤其整数用 Varint) |
使用场景 | 本地缓存、同语言进程间通信 | 微服务 RPC、异构系统对接、长期存储数据 |
// Java 原生序列化
UserMsg msg = new UserMsg("Tom", 20);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(msg);
byte[] data = baos.toByteArray(); // ❌ 只有 Java 能读
•
包含类名、版本号、字段描述等大量元信息。
•
换个语言(Go/C++)直接无法解析。
// C++ 序列化
UserMsg msg;
msg.set_name("Tom");
msg.set_age(20);
std::string data = msg.SerializeAsString(); // ✅ 任何语言都能解析
// Python 反序列化
import user_msg_pb2
msg = user_msg_pb2.UserMsg()
msg.ParseFromString(data) // 拿到 "Tom", 20
•
数据格式纯粹,只有字段编号+值。
•
IDL 描述明确,谁都能生成代码。
IDL,Interface description language,即接口描述语言。
IDL是一种很有用的工具,它提供了对接口的描述,约定了接口协议。‘使得通讯双方通讯时,无需再发送 scheme,有效提高了通讯数据的荷载比。
首先,依据 IDL 生成对应的客户端和接口模块,这个本质是编译。
直接序列化 本质上把“数据的形状”(Schema)隐藏在了代码和二进制流里,别人没法独立还原。
IDL + 序列化 把 Schema 显式写出来,成为团队/跨团队、跨语言、跨时间的“共同约定”——这才是分布式系统里最宝贵的资产。
在window平台 source insight 显示是对齐的为到了 ,liunx平台 4空格变成8空格 set list
•
source insight 4.0对齐提示设置
•
https://visualgdb.com/gdbreference/commands/set_args set args [Arguments] show args Arguments Specifies the default command-line arguments that will be passed to the program.
•
https://www.geeksforgeeks.org/linux-unix/how-to-pass-command-line-arguments-to-gdb-in-a-linux-environment/
不要独自一个人看手机,
我们常常陷入这样的场景: 独自一人时,在餐厅、地铁、卧室、沙发或书桌前, 当你躺在那里,趴在哪里,做在哪里时候,身体固定狭小空间,无法互动 ,不自觉地掏出手机。 身体被困在狭小的物理空间里,无法动弹, 只能目光便只能被那方寸屏幕牢牢吸引, 你行为被 多巴胺诱惑,简单舒服即使反馈奖励 ,被平台设计各种陷阱控制
除非拥有极强的意志力,根本不选择痛苦迟到的奖励
与其对抗本能,甚至平台 不如改变环境。 请选择去户外,去操场,视眼开阔 看手机。 请主动为你的手机使用选择更健康的场景
•
进入公司开始工作时
•
下班回到家中时
•
在餐厅用餐或社交时
•
乘坐地铁通勤时
行动建议:
•
在上述场景开始时,立刻将手机放入书包或固定在某个位置(如抽屉)。
•
给自己设定一个专注时限,例如至少接下来的3小时内不主动查看。
•
这能有效打破“无聊就刷手机”的循环,把注意力还给当下的人和事。
核心行动准则2:换个开阔的地方看手机
•
早晨起床后
•
下班之后
•
周末时光 行动建议:
•
可以选择去图书馆、咖啡馆、商场中庭或景点休息区,公司园区,马路边
•
在这些具有公共生活感的场所使用手机,
•
周围的环境流动能天然地分散你对屏幕的过度专注,避免陷入无休止的刷屏。
一句话描述:
普通人最简单方式,重启自己操作系统
•
固定21点入睡:1 R90睡眠方案之所以能这样的世界顶尖运动员所青睐,每天晚上的睡眠规律你可以
•
固定6点起床:2 成不了作家 你可以打开笔记本写一行文字,3 做不出产品产品你打开软件写一行代码,4 无法演讲信服的话,你自己说一句话。5 成不运动健身达人 你走到运动走一步