程序怎样开始执行

源代码经过编译或解释体系转化为机器可执行的操作。典型本地程序经历预处理、编译、汇编和链接;加载器把可执行文件及依赖映射到进程地址空间,运行时再进入程序入口。具体过程随语言和平台变化,不能把一个语言的运行时等同于全部计算机。

CPU 根据指令进行计算与访存。寄存器、缓存和主存承担不同层次的存储;连续访问通常更利于利用局部性,但实际性能还受工作集、分支、带宽和编译优化影响,需要测量验证。

地址空间不是整机内存的照片

虚拟内存为进程提供地址空间,页表负责映射,权限控制读、写和执行。进程申请地址区间与实际占用物理页并非同一时刻。程序的栈、动态分配区域、静态数据和代码通常具有不同的生命周期与访问规则,具体布局由平台决定。

import struct

raw = bytes([0x01, 0x02])
assert struct.unpack(">H", raw)[0] == 258
assert struct.unpack("<H", raw)[0] == 513

同一组字节按不同字节序解释会得到不同数值。网络协议、文件格式和传感器数据都需要明确字节序、宽度、有无符号及单位,不能直接依赖当前机器的默认格式。

排障时看什么

内存问题至少区分:越界、悬空引用、泄漏、持续增长的缓存和合法的大工作集。观察驻留内存、分配频率与对象生命周期,再结合复现步骤分析;仅看到内存没有立刻回落,不能直接断定泄漏。

练习与面试自查

把 16 位传感器数据写成固定字节序,再读回验证。解释程序为何可以在链接时找不到符号、运行时找不到动态库,或执行后访问非法地址,这三类失败分别发生在哪里。

进一步比较按行与按列遍历大矩阵的运行时间,记录矩阵大小、表示方式和重复次数,不把单次计时当作硬件结论。

参考资料