<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>拾光集</title><description>按章节地图推进的技术笔记：C 语言、C++、数据结构、并发、Qt 6、Windows/Win32、Linux、操作系统、网络、嵌入式、数据库、构建与调试。基于 Astro 构建，部署在 GitHub Pages。</description><link>https://wty.blogs.abrdns.com/</link><language>zh-CN</language><item><title>CMake 现代用法：生成器决定一切形状，可见性关键字决定谁能编译过</title><link>https://wty.blogs.abrdns.com/posts/build-cmake-target-model-and-generators/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/build-cmake-target-model-and-generators/</guid><description>实测：本机 CMake 3.30.5 的生成器列表里最高只到 &quot;Visual Studio 17 2022&quot;（被标为默认），而 PATH 上明明装着 VS 18； 同一个工程不写 `-G` 时 `CMAKE_CONFIGURATION_TYPES=Debug;Release;MinSizeRel;RelWithDebInfo`、 `CMAKE_BUILD_TYPE` 为空，写 `-G &quot;MinGW Makefiles&quot;` 时两者都是空串。多配置目录里 `cmake --build` 不带 `--config` 就落在 Debug，加了 `--config Release` 之后 Debug 与 Release 两份 exe **同时存在**； 单配置生成器加 `--config` 是 rc=0 静默忽略。`CMAKE_BUILD_TYPE=Release` 在 flags.make 里展开成 `-O3 -DNDEBUG`，Debug 只有 `-g`。可见性实测：`PRIVATE` 的头目录不传播，消费者直接 `fatal error: core.h: No such file or directory`，`PUBLIC` 才编得过；`INTERFACE` 库的 `-DINTF_MARK=11` 出现在 compile_commands.json（5 条）里。`find_package(Boost REQUIRED)` 失败是 rc=1 带 FindPackageHandleStandardArgs 调用栈，不加 REQUIRED 就 rc=0 且 `Boost_FOUND` 为空。 把别的源码目录指到同一个 `-B` 会得到 &quot;does not match the source … used to generate cache&quot;。</description><pubDate>Fri, 16 Oct 2026 00:00:00 GMT</pubDate><category>编译构建</category><category>CMake</category><category>生成器</category><category>目标属性</category></item><item><title>构建配置与编译选项：警告集、优化档、标准版本，以及那些在本机是空操作的开关</title><link>https://wty.blogs.abrdns.com/posts/build-configuration-and-compiler-flags/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/build-configuration-and-compiler-flags/</guid><description>实测：同一份带 3 处问题的源码，默认零警告、`-Wall` 报 1 条、`-Wall -Wextra` 2 条、再加 `-Wshadow` 3 条； `-Wall -Werror` 退出码 1 并打出 `[-Werror=unused-variable]`，而把它排在后面的 `-Wno-unused-variable` 一加就回到 0 （**最后一个赢**）。MinGW 上 `sizeof(wchar_t)=2`，加不加 `-fshort-wchar` 都一样；`(char)-1 &gt; 0` 为 0（char 有符号）。 `-std` 档位读回：C 是 c89 无 `__STDC_VERSION__`、c99=199901、c11=201112、c17=201710、c2x=202000；C++ 是 c++11=201103…c++23=**202100**，而 `-std=c++2c` 直接 `unrecognized command-line option`。 `-fPIC`/`-fPIE`/`-fno-pic` 三个开关产出的 `.text` 与重定位数**逐字节相同**（x86-64 Windows 恒为 PIC）。 `-m32` 能编译出 `pe-i386` 的目标文件，但链接阶段一路 `skipping incompatible …libmingw32.a`。 调试信息：`-O0 -g3` 让 exe 从 77138 涨到 111720（`.debug*` 8 段 39220 字节），`-O2 -g` 只涨 3936 字节（9 段 7788）。</description><pubDate>Fri, 16 Oct 2026 00:00:00 GMT</pubDate><category>编译构建</category><category>编译选项</category><category>GCC</category><category>优化级别</category><category>ABI</category></item><item><title>交叉编译工具链：从编译器自己报出的那串名字读懂 triplet、sysroot 与前缀</title><link>https://wty.blogs.abrdns.com/posts/build-cross-toolchains-and-triplets/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/build-cross-toolchains-and-triplets/</guid><description>实测：本机 `gcc -dumpmachine` 给出 `x86_64-w64-mingw32`，`--print-multi-lib` 只有一行 `.;`（没有第二套子库）， 而 `--print-sysroot` 把构建机路径原样吐出来： `C:/buildroot/x86_64-1310-posix-seh-msvcrt-rt_v11-rev1/mingw64`——**这一串就是 triplet 该读懂的全部字段** （架构/版本/线程模型 posix/异常模型 seh/CRT msvcrt/运行库版本/修订号）。把 `--sysroot` 指到一个不存在的目录， 编译**照样 rc=0**；而 `-isystem` 指到不存在目录时立刻 `fatal error: nosuchhdr.h: No such file or directory`—— 说明这个 native 构建里 sysroot 基本不参与搜索，头路径靠的是 `-isystem`/`-I` 与内建前缀。 用 `-m32` 做的受控&quot;伪交叉&quot;能编出 `pe-i386` 目标文件，链接则报 `i386 architecture of input file … is incompatible with i386:x86-64 output`。 本机没有 `arm-none-eabi-gcc`、没有 `aarch64-w64-mingw32-gcc`、没有 vcpkg/conan/ccache，真目标平台的编译一律未实测。</description><pubDate>Fri, 16 Oct 2026 00:00:00 GMT</pubDate><category>编译构建</category><category>交叉编译</category><category>工具链</category><category>triplet</category><category>sysroot</category></item><item><title>链接与符号问题诊断：undefined reference 怎么读、缺 DLL 和缺入口点为什么是同一个退出码</title><link>https://wty.blogs.abrdns.com/posts/build-link-and-symbol-troubleshooting/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/build-link-and-symbol-troubleshooting/</guid><description>实测：`extern &quot;C&quot;` 头配 C++ 实现时，报错是 `undefined reference to &apos;calc&apos;`，而 `nm` 显示请求侧是 `U calc`、供给侧是 `T _Z4calci`；反过来 C++ 调用 C 实现时 ld 默认把名字反修饰成 `undefined reference to &apos;calc(int)&apos;`——**好看的报错反而藏住了你要 grep 的符号名**，加 `-Wl,--no-demangle` 才还原成 `_Z4calci`。`-Wl,-y,符号` 在本机**对 .o 和归档两种来源都没有输出**， 能用的是 `-Wl,--trace`（它按顺序列出 crt2.o / crtbegin.o / … / libstdc++.dll.a / libmingw32.a / libgcc_s.a / libmsvcrt.a / libkernel32.a / crtend.o）。运行时&quot;找不到 DLL&quot;和&quot;找不到导出函数&quot; 在 Git Bash 与 cmd 下都报 **127**，用看门狗 `GetExitCodeProcess` 才拿到真值： 前者 `0xC0000135`(3221225781)，后者同样是非 0，而全局构造里空指针写是 `0xC0000005`(3221225477)。</description><pubDate>Fri, 16 Oct 2026 00:00:00 GMT</pubDate><category>编译构建</category><category>链接错误</category><category>符号表</category><category>MinGW</category><category>退出码</category></item><item><title>Makefile 基础：规则、自动变量与增量构建，以及 Windows 上 make 自己会怎么崩</title><link>https://wty.blogs.abrdns.com/posts/build-makefile-rules-and-incremental/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/build-makefile-rules-and-incremental/</guid><description>实测：这台机器上有三个 make 但没有一个叫 `make`（`mingw32-make.exe` 是 GNU Make 4.2.1 x86_64， `C:\Strawberry\c\bin\gmake.exe` 是 4.1 **32 位**）；同一行 `OBJS = $(wildcard *.c:.c=.o)` 让前者**零输出退出 127**、让后者抛出 `Interrupt/Exception caught (code = 0xc0000005)` 退出 255； 没设 `SHELL` 且 PATH 只剩 System32 时，`rm -rf` 变成 `process_begin: CreateProcess(NULL, rm -rf build, ...) failed. make (e=2)`；改一个被 3 个 .c 包含的头文件，手写依赖的 Makefile 重建 **0 个** .o，加 `-MMD -MP` 后重建 3 个；同一份 Makefile， `-j1` 三次全绿、`-j8` 五次全红；201 个文件全量 34.1 s、`-j8` 13.0 s、只改一个文件 2.4 s、 什么都不改 1.7 s。</description><pubDate>Fri, 16 Oct 2026 00:00:00 GMT</pubDate><category>编译构建</category><category>Makefile</category><category>GNU Make</category><category>MinGW</category><category>增量构建</category></item><item><title>静态库、动态库与链接顺序：归档怎么扫、导入库是什么、缺 DLL 时谁先被找到</title><link>https://wty.blogs.abrdns.com/posts/build-static-shared-libraries-and-link-order/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/build-static-shared-libraries-and-link-order/</guid><description>实测：两个 .o 共 1488 字节，打进 `libab.a` 是 1698 字节（容器+索引 210 字节）；`main.o liba.a libb.a` 链接成功，把两个库顺序调换成 `main.o libb.a liba.a` 就报 `liba.a(a.o):a.c:(.text+0x9): undefined reference to &apos;b_fn&apos;`，同一个归档里则两种顺序都成功； `--start-group` 能救回来。两个成员都定义 `b_fn` 时，只用得到一个符号的场景**静默取第一个**（退出码证明）， 强制两个都进来才报 `multiple definition`。一个只导出一个函数的 DLL 是 36293 字节，配套导入库 `libfoo.dll.a` 只有 1496 字节；`--version-script` 在 PE 上被**完全忽略**（`local: add3` 之后导出表还是 1 条，退出码 0）； exe 同目录的 DLL 赢过 PATH 里的同名 DLL，两份都没有时 Git Bash 报 127。</description><pubDate>Fri, 16 Oct 2026 00:00:00 GMT</pubDate><category>编译构建</category><category>静态库</category><category>动态库</category><category>链接顺序</category><category>MinGW</category></item><item><title>索引原理与失效场景：把数据库文件剖开看树，再用 40 条 EXPLAIN QUERY PLAN 原文钉死最左前缀</title><link>https://wty.blogs.abrdns.com/posts/db-index-principles-and-failures/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/db-index-principles-and-failures/</guid><description>实测：10 万行的表占 909 页、树高 3 层，索引 i_c 占 259 页、树高 2 层，每个索引的字节数都精确等于&quot;页数 × 4096&quot;（+1060864 字节 = 259 页，一页不多）；索引的内部页存的是**完整 key + rowid**，表的内部页只存 rowid；(a,b,c) 上 `WHERE b=500` 的计划是 `SCAN`、`a=500 AND c=500` 只用到 `(a=?)`、`a&gt;500 AND b=500` 只用到 `(a&gt;?)`；`lower(name)=…` 16.2 ms，建表达式索引后 0.168 ms（96 倍）；`a=5 OR pad=&apos;zz&apos;` 走 `MULTI-INDEX OR`（0.135 ms）而 `a=5 OR b=5` 退回 `SCAN`（3.35 ms）；TEXT 亲和列拿整数比照样走索引，BLOB 亲和列拿整数比会**静默少行**（4 行只查到 2 行）；同一谓词下 50% 命中范围取未索引列 178 ms、走覆盖索引 1.08 ms（165 倍）；首列只有 5 个值时 SQLite 不做跳扫，但扫窄索引比扫表快 3.7 倍，与页账本算出来的 3.5 倍对上；4 个索引让 20000 行插入慢 1.34 倍。</description><pubDate>Fri, 16 Oct 2026 00:00:00 GMT</pubDate><category>数据库</category><category>SQLite</category><category>索引</category><category>B+树</category><category>查询计划</category></item><item><title>查询：JOIN、子查询与聚合——四种 JOIN 的行数、NULL 把 NOT IN 变成空集、同一语义 13 种写法的实测</title><link>https://wty.blogs.abrdns.com/posts/db-joins-subqueries-and-aggregates/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/db-joins-subqueries-and-aggregates/</guid><description>实测：`dept_id &lt;&gt; 10` 少掉 1 行 NULL；子查询里一个 NULL 让 `NOT IN` 从 7 行变 0 行；`count(*)=7` 而 `count(dept_id)=6`，`avg` 的分母是 6 不是 7；LEFT JOIN 条件写在 ON 里 1364 行、写在 WHERE 里 1008 行；10 万行上同一语义的 5 种写法差 3.8 倍（IN 10.3 ms vs 标量相关子查询 39.6 ms）；给 orders 加两个索引后，一条 LEFT JOIN 从 9.7 ms 变成 57.8 ms（慢 6.0 倍），补一个覆盖索引才翻回 3.3 ms；`OFFSET 50000` 52.8 ms vs 键集分页 0.113 ms。</description><pubDate>Fri, 16 Oct 2026 00:00:00 GMT</pubDate><category>数据库</category><category>SQL</category><category>SQLite</category><category>Qt SQL</category><category>JOIN</category><category>子查询</category><category>聚合函数</category><category>NULL</category></item><item><title>窗口函数与 CTE：默认帧让累计和翻倍、递归 CTE 会挂死、把 1000 次循环压成一条 SQL 实测快 170 倍</title><link>https://wty.blogs.abrdns.com/posts/db-window-functions-and-recursive-ctes/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/db-window-functions-and-recursive-ctes/</guid><description>实测：`sum() over (order by v)` 的默认 RANGE 帧把并列行全算进来，10 万行里 99900 行的累计值与 ROWS 帧不同；`last_value` 默认帧右端就是当前行；`row_number`/`rank`/`dense_rank` 取每组前 3 实测给 3000 / 3008 / 3000 行，`max` 连接只给 1006 行；`row_number()` 进 WHERE 报 `misuse of window function row_number()`；`generate_series` 报 `no such table: generate_series`；递归 CTE 不带截断条件遇环跑满 40 s 未返回被 timeout 杀掉，而 `select v from 无上界递归 limit 5` 正常返回 1..5；1000 次 N+1 点查中位 11282 ms vs 一条 GROUP BY 66.3 ms（中位 170 倍）；给每笔订单写 Top3 标签，应用层逐行 UPDATE 1204 ms vs `UPDATE FROM`+窗口 552 ms（2.18 倍）。</description><pubDate>Fri, 16 Oct 2026 00:00:00 GMT</pubDate><category>数据库</category><category>SQL</category><category>SQLite</category><category>Qt SQL</category><category>窗口函数</category><category>CTE</category><category>递归查询</category><category>TopN</category></item><item><title>读汇编与编译器优化：调用约定、栈帧、向量化，以及让 GCC 自己交代为什么没向量化</title><link>https://wty.blogs.abrdns.com/posts/dbg-asm-and-compiler-optimization/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/dbg-asm-and-compiler-optimization/</guid><description>实测：`int sixargs(int a,int b,int c,int d,int e,int f)` 在 MS x64 下前四个参数落在 `ecx/edx/r8d/r9d`，第 5、6 个从 `0x28(%rsp)`、`0x30(%rsp)` 取——**偏移 0x20 就是那 32 字节 shadow space**； 16 字节结构体按值传参编成 `mov (%rcx),%rax; add 0x8(%rcx),%rax`，即**隐式传指针**； `int leaf(int x){return x&gt;0?x:-x;}` 编成 4 条无分支指令 `mov/cltd/xor/sub`，**没有 prologue 也没有 epilogue**。 同一个整数求和循环：`-O2` 下**没有一条向量指令**（`movslq/add/cmp/jne` 的标量环）， `-O3 -fopt-info-vec` 让 GCC 自己打印 `a1.c:10:23: optimized: loop vectorized using 16 byte vectors`， 而另外三个循环的 missed 理由分别是 `couldn&apos;t vectorize loop`、`not vectorized: unsupported data-type`、 `not vectorized: complicated access pattern.`；`-O3 -mavx2 -ftree-vectorize` 后该函数出现 19 条向量指令。 `-fno-strict-aliasing` 在这个样本上指令数一模一样（13 条 vs 13 条）——**因为那个循环本来就没被向量化**。</description><pubDate>Fri, 16 Oct 2026 00:00:00 GMT</pubDate><category>调试</category><category>汇编</category><category>x86-64</category><category>调用约定</category><category>自动向量化</category></item><item><title>基准测试方法论：先证明被测代码还在，再谈那个数字</title><link>https://wty.blogs.abrdns.com/posts/dbg-benchmark-methodology/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/dbg-benchmark-methodology/</guid><description>实测：本机 QPC 频率 10 MHz ⇒ 分辨率 100 ns，两次连续调用之差是 0 个 tick，所以&quot;100 ns&quot;这类结果等于没测到； `-O2` 下把结果丢弃的 100 万次 xorshift 循环，函数体**只剩一条 `ret`**，测得 0.00 ns/次，而写入 `volatile` 的版本是 2.22 ns/次、`-O0` 三个版本都是 6.87–7.90 ns/次；`for(int i=0;i&lt;1000000;i++);` 在 `-O2` 下整条消失； 100 次 `gcc -fsyntax-only` 花 16505 ms（**165 ms/次**，比多数被测代码本身更贵）；开 6 个 CPU 抢占者重测， 依赖链微基准 2.22→2.19 ns、进程启动型 16505→16741 ms、`Sleep(10)` 平均超出 5.29→5.26 ms， 三类都只动 ±1.4%——污染真正打击的是等待型与 IO 型测量，不是所有测量。</description><pubDate>Fri, 16 Oct 2026 00:00:00 GMT</pubDate><category>基准测试</category><category>性能优化</category><category>统计</category><category>编译器优化</category></item><item><title>瓶颈定位与优化次序：先判是哪一类（IO / CPU / 锁 / 数据布局），再决定动谁</title><link>https://wty.blogs.abrdns.com/posts/dbg-bottleneck-priority/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/dbg-bottleneck-priority/</guid><description>汇总本专栏已实测的数字给出次序：直读随机 4 KB 是缓冲读法的 10.5 倍（75.64 vs 7.19 µs/次），把队列深度从 1 加到 16 又能把单价从 68.40 压到 13.16 µs——**同一个 IO 瓶颈，&quot;换访问方式&quot;值 10 倍、&quot;加并发&quot;值 5 倍**； 每行 `fflush` 是 1MB 缓冲的 31 倍（8195 ns/行），而把全局锁换成每线程私有缓冲是 8.5 倍（811.6 → 95.6 ns/行）； 一次条件变量唤醒 11.35 µs 等于 186 次原子自旋交接（61 ns）；201 个文件的编译全量 34.1 s，`-j8` 只买到 2.63 倍， 而&quot;改一个文件别全量重编&quot;值 14.1 倍——**依赖图比并行度便宜**；数据库那条加了两个索引反而慢 6.0 倍 （9.653 → 57.783 ms）、换成覆盖索引才回到 3.288 ms——**同一个&quot;优化动作&quot;可以是反向的**。 本文不新增任何测量，只做一件事：把这些数字排成一个可执行的判断顺序。</description><pubDate>Fri, 16 Oct 2026 00:00:00 GMT</pubDate><category>性能优化</category><category>瓶颈定位</category><category>方法论</category><category>IO</category><category>锁</category></item><item><title>崩溃现场与 core dump：退出码、minidump 与符号缺失</title><link>https://wty.blogs.abrdns.com/posts/dbg-crash/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/dbg-crash/</guid><description>实测（Windows 侧）：递归爆栈与 `alloca(512MB)` 两份 minidump 的字节数完全相同（12,354,409），但 `rbp−rsp` 一个是 2,076,224、一个是 72 字节；在栈溢出的 handler 里写 dump，四条自救路线全留下 0 字节文件，而且进程终止码 从 0xC00000FD 被改成 0xC0000005；minidump 体积差 1,159 倍（36,065 → 41,781,049 字节）写盘时间却只差 1.09 倍； 运行期整数除零是 0xC0000094、能被编译期证明的除零被 GCC 折成 `ud2` 于是变成 0xC000001D；MinGW 的 dbghelp `Sym*` 对 `-g0`/`-g3`/stripped 三种产物一律 0 命中；Linux 的 core、`ulimit -c`、`core_pattern` 与嵌入式收集本机未实测。</description><pubDate>Fri, 16 Oct 2026 00:00:00 GMT</pubDate><category>调试</category><category>崩溃</category><category>minidump</category><category>WER</category></item><item><title>缓存友好与数据布局——本机分层延迟拐点、2.77 倍的 AoS/SoA 与测不出来的跨行惩罚</title><link>https://wty.blogs.abrdns.com/posts/dbg-data-layout/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/dbg-data-layout/</guid><description>实测：同一块 128 MB 内存，随机跳一条 64 字节记录 **99.34 ns**，顺序扫同一个跨度 **3.68 ns**，差 **27.0 倍**； 分层拐点在 48→64 KB（1.38→3.66 ns）、1→2 MB（5.59→19.59）、2→4 MB（19.59→99.34）三处； 步长 1→8（正好每行取一个）单次触碰 0.51→1.38 ns，而每纳秒拿到的有用字节从 15.6 掉到 5.8； 手工 `__builtin_prefetch` 在顺序扫描上**没有任何一档快过不发预取**，dist=16 反而慢 5.0 倍（0.413→2.076 ns/元素）； AoS/SoA 只读 1 个字段是 2.77 倍、读全部 4 个字段仍有 2.31 倍（两边字节数完全相同，故这一半是向量化质量，关掉向量化后缩成 1.64）； 把 4 字节热字段和 60 字节冷字段挤在同一只 64 字节对象里，只读热字段是 3.09–3.39 ns/只，分离成纯热数组是 0.20–0.21，**15.8 倍**； 分支预测：随机数据 `if` 2.899 ns/元素、有序 0.371（**7.81 倍**），换成三目后随机与有序差 **1.01 倍**； 而&quot;跨缓存行的 8 字节读&quot;在本机测不出惩罚（比值 0.973/0.986/0.707，落在噪声内）。</description><pubDate>Fri, 16 Oct 2026 00:00:00 GMT</pubDate><category>调试</category><category>缓存</category><category>数据布局</category><category>分支预测</category><category>性能优化</category></item><item><title>内存泄漏与碎片——把&quot;内存不降&quot;拆成三件可以分别测量的事</title><link>https://wty.blogs.abrdns.com/posts/dbg-memory/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/dbg-memory/</guid><description>实测（Windows 侧）：交错释放一半 10 万个 80 字节块之后，私有内存 **一个字节都没降**（10,153,984 → 10,153,984）， 而 `HeapWalk` 数出堆里空着 5,502,336 字节、分散在 50,098 个空闲块里、**最大的一块只有 208 字节**；同样这批块改成顺序释放， priv 立刻掉 12,152,832 字节；`malloc` 的尺寸阶梯在 **1,048,576 字节处翻转**——以下 free 后 100% 留在堆里，以上 free 后归还 0%； 每泄漏一只 128 字节对象实测带走 152.9 字节（49 轮拟合，轮增量 275,251 字节/轮）；20 万次 96 字节的 `malloc`/`free` 换成一次 `VirtualAlloc` 加切块，单只借还从 94.0ns 降到 14.7ns（6.4 倍）、整轮 18.644ms 降到 7.839ms（2.38 倍）， 代价是峰值从&quot;用多少占多少&quot;变成一次性全额提交 20,844,544 字节。Valgrind/massif/heaptrack/`/proc/smaps`/`perf` 本机无 Linux 与容器，**全部未实测**，本文只给 Windows 侧的等价物和它的失效条件。</description><pubDate>Fri, 16 Oct 2026 00:00:00 GMT</pubDate><category>调试</category><category>内存泄漏</category><category>内存碎片</category><category>分配器</category><category>性能优化</category></item><item><title>CI/CD 与脚本化：门禁要验产物，不验步骤退出码</title><link>https://wty.blogs.abrdns.com/posts/engineering-ci-cd-and-scripting/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/engineering-ci-cd-and-scripting/</guid><description>实测一条 8 阶段本机流水线（总 5807ms）里的四种假绿：阶段函数返回 0 让整体 rc=0 而 report 里躺着两行 rc≠0；`gate | head -1` 把 rc=1 变成 rc=0；`make` 说 Nothing to be done 且 rc=0；产物里的构建号被冻在第一次的值。另测：`SOURCE_DATE_EPOCH` 被 MinGW 忽略、`-Wl,--no-insert-timestamp` 有效但随后的 `strip` 又把时间戳盖回来。</description><pubDate>Fri, 16 Oct 2026 00:00:00 GMT</pubDate><category>工程实践</category><category>CI</category><category>CD</category><category>流水线</category><category>门禁</category><category>可观测</category></item><item><title>模块划分与依赖管理：分层要靠链接器证明，不是靠目录树</title><link>https://wty.blogs.abrdns.com/posts/engineering-module-boundaries-and-dependencies/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/engineering-module-boundaries-and-dependencies/</guid><description>实测：一个 4 模块 11 条边的迷你工程里 3 条反向依赖把全部模块粘成一个 4 元强连通分量，而 `make` 全程退出码 0、零警告、程序跑对；把模块拆成 4 个静态库后两种链接顺序都报 undefined reference（无解），`--start-group` 能救；穷举 84 种三元割集只有 5 种能破环，其中仅 1 种是&quot;只拆违规边&quot;。</description><pubDate>Fri, 16 Oct 2026 00:00:00 GMT</pubDate><category>工程实践</category><category>模块化</category><category>依赖管理</category><category>循环依赖</category><category>插件化</category></item><item><title>重构与小步安全改动</title><link>https://wty.blogs.abrdns.com/posts/engineering-refactor-small-steps/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/engineering-refactor-small-steps/</guid><description>实测：手滑把 qty &gt; 10 写成 qty &gt;= 10，只改动 3780 例基线里的 3.0%；naive sed 改名 13 处全中、编译零错误，却让 105 行输出 100% 变化——小步的前提是先有一台会咬人的机器。</description><pubDate>Fri, 16 Oct 2026 00:00:00 GMT</pubDate><category>重构</category><category>工程实践</category></item><item><title>版本号、发布与回滚：兼容性的裁判是已编译的调用方，不是你的语义直觉</title><link>https://wty.blogs.abrdns.com/posts/engineering-version-release-and-rollback/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/engineering-version-release-and-rollback/</guid><description>实测：给结构体尾部加一个字段（语义化版本里的典型 MINOR 改动），已编译的调用方不崩、退出码 0，但它把邻居内存写成了 0x11223344；中间插字段则让调用方把 999 当成 c 读走；同一份源码用同一组参数编两次，84932 字节里有 2 个字节不同；`--force-with-lease` 在 fetch 之后照样把别人的提交抹掉。</description><pubDate>Fri, 16 Oct 2026 00:00:00 GMT</pubDate><category>工程实践</category><category>版本号</category><category>发布</category><category>回滚</category><category>符号归档</category></item><item><title>socket 编程基础</title><link>https://wty.blogs.abrdns.com/posts/net-socket-programming/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/net-socket-programming/</guid><description>实测：Windows 上第二个 socket 带 SO_REUSEADDR 去 bind 完全相同的 127.0.0.1:19890 得到 10013（WSAEACCES），而 bind(0.0.0.0:19890) 不设任何选项就能成功；SO_EXCLUSIVEADDRUSE 在场时带 SO_REUSEADDR 的后来者拿 10013；SO_RCVTIMEO=700ms 的 recv 返回 -1 且错误码是 10060（WSAETIMEDOUT）而不是 10035，三次实测 703.0/705.7/710.4ms；SO_SNDTIMEO=200ms 管不住 connect，死端口照样花 2029.9ms 才返回 10061；不设 SO_SNDTIMEO 的第 5 次 send(65536) 卡住 22 秒没返回被 timeout 杀掉；粘包那场抓包 98 条、载荷合计 121 字节与应用侧发出数完全相等，3 次 send(10) 在线上仍是 3 段 payload=10 —— 粘的是读法，不是网络。</description><pubDate>Fri, 16 Oct 2026 00:00:00 GMT</pubDate><category>网络</category><category>socket</category><category>Winsock</category><category>字节序</category><category>getaddrinfo</category><category>select</category><category>粘包</category><category>超时</category></item><item><title>滑动窗口与拥塞控制</title><link>https://wty.blogs.abrdns.com/posts/net-tcp-flow-control-and-congestion/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/net-tcp-flow-control-and-congestion/</guid><description>实测：本机接收窗口自动调谐把通告窗口从 65280 抬到 261888 字节；8 MB 回环传输的 61 条纯 ACK 里有 41 条各确认整 65536 字节（=两次应用写切出的 2 个段），与 netsh 读回的&quot;延迟 ACK 频率 2&quot;对齐；零窗后发送端按 315.0/605.5/1211.4 毫秒翻倍探测；整场传输 cwnd 恒为 654950 字节 = 10×MSS，与 netsh 的&quot;初始拥塞窗口 10 MSS&quot;对上，而 SndLimTransCwnd=0 说明它一次都没限制过发送；TCP_NODELAY 开关在回环上对 8 次单字节写毫无差别（都是 8 段、每条自带一个 ACK）。</description><pubDate>Fri, 16 Oct 2026 00:00:00 GMT</pubDate><category>网络</category><category>TCP</category><category>滑动窗口</category><category>拥塞控制</category><category>Nagle</category><category>延迟确认</category></item><item><title>UDP 与 QUIC</title><link>https://wty.blogs.abrdns.com/posts/net-udp-quic/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/net-udp-quic/</guid><description>实测：本机 sendto 上限 65507 字节，65508 起报 10040（WSAEMSGSIZE），且 IP_DONTFRAGMENT 开与关返回值一字不差；20000 个 8192 字节数据报打向 SO_RCVBUF=8192 的接收端，发送端 20000/20000 全部成功返回，接收端只读到 18160 个（丢 1840=9.2%），改成 16 MB 则 20000 个一个不少；自写 ARQ 在 RTO=30/100/300 ms 三档下发出 541/495/495 个数据报、重传节拍 16/13/13 次、用时中位 950.4/1968.8/4534.4 ms；组播 239.1.1.1 发出 20 收到 20、退组后再发 5 个收到 0 个；受限广播线上 11 个包而应用侧读到 21 个。QUIC 与 0-RTT 本机无服务端，未实测。</description><pubDate>Fri, 16 Oct 2026 00:00:00 GMT</pubDate><category>网络</category><category>UDP</category><category>QUIC</category><category>组播</category><category>广播</category><category>可靠传输</category><category>ARQ</category><category>ICMP</category></item><item><title>IO 栈、页缓存与异步 IO</title><link>https://wty.blogs.abrdns.com/posts/os-io-stack/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/os-io-stack/</guid><description>实测：同一个 128 MB 文件，缓冲随机 4 KB 读中位 7.19 微秒/次、FILE_FLAG_NO_BUFFERING 同请求 75.64 微秒/次（10.5 倍）；队列深度从 1 加到 16 把直读单价从 68.40 微秒压到 13.16 微秒，再加到 64 反而回落到 18.14。NO_BUFFERING 的三条约束里，缓冲区与长度不当会当场报 87（参数错误），而偏移不对齐是 SetFilePointerEx 悄悄失败——返回 0、文件位置不动，随后的 WriteFile 照样返回成功、写的却是上一个位置 （请求 100、落在 0，字节级取证见正文）。FlushFileBuffers 第一次 64 MB 收 28.63 毫秒、第二次只 0.057 毫秒；写完关掉句柄闲置 3 秒，脏页仍在。映射视图写 4 KB 首遍 1.72 微秒/页、第二遍 0.18 微秒，同一批偏移 走 WriteFile 要 21.86 微秒。同步句柄上 ReadFileEx 投 3 次完成例程只交付 1 次，而 SleepEx(1,TRUE) 一次真实阻塞 15.2 毫秒。</description><pubDate>Fri, 16 Oct 2026 00:00:00 GMT</pubDate><category>操作系统</category><category>IO</category><category>页缓存</category><category>异步IO</category></item><item><title>文件系统与 VFS</title><link>https://wty.blogs.abrdns.com/posts/os-ntfs-filesystem-and-vfs/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/os-ntfs-filesystem-and-vfs/</guid><description>实测：NTFS 上 `GetFileInformationByHandle` 给的 FileId64 高 16 位是序列号、低 48 位是 MFT 记录号，连做 12 轮&quot;建→删&quot;有 11 次复用同一条记录而序列号从 17 涨到 28；加一个硬链接 ID 不变、链接数 1→2，最后一个名字删掉后按路径重开报 2 而旧句柄仍读得到；5000 项目的录里按名打开要 356–461 微秒，只有 1 个文件的目录里 60–84 微秒，而批量枚举只要 1.40–1.45 微秒/项；缓冲写 4 KB 是 9.7–13.6 微秒、WRITE_THROUGH 47–112 微秒、NO_BUFFERING 31–48 微秒；稀疏文件写 4096 B 实占 65536 B、67 MB 逻辑只占 131072 B；符号链接两次都报 1314，目录联接成功并把路径解析到同一个 FileId。</description><pubDate>Fri, 16 Oct 2026 00:00:00 GMT</pubDate><category>操作系统</category><category>文件系统</category><category>NTFS</category><category>VFS</category><category>inode</category><category>目录项</category><category>硬链接</category></item><item><title>虚拟内存、分页与 TLB</title><link>https://wty.blogs.abrdns.com/posts/os-page-table-tlb-and-page-faults/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/os-page-table-tlb-and-page-faults/</guid><description>实测：依赖载入链只涉及 32 个页时 3.74 纳秒/次访问，512 页 16.54 纳秒、8192 页 111.60 纳秒（29.5 倍）；同一批 512 页改成每页连续命中 16 次就降到 2.56 纳秒（6.1 倍）；给被追的 256 页各改一次保护位会把它们踢出工作集（-1048576 B、缺页 +256），回来后每页 654.69 纳秒，是热态的 119.7 倍；匿名页首触碰 466 纳秒/页，文件映射页 1006–1299 纳秒/页；FILE_MAP_COPY 视图写 2048 页缺页 +0 而文件原字节未变；用户态自己做请求分页 5029–5892 纳秒/页，是内核按需提交的 10.8–12.6 倍。</description><pubDate>Fri, 16 Oct 2026 00:00:00 GMT</pubDate><category>操作系统</category><category>虚拟内存</category><category>页表</category><category>TLB</category><category>缺页中断</category><category>COW</category></item><item><title>Qt 6 跨平台与部署</title><link>https://wty.blogs.abrdns.com/posts/qt6-cross-platform-and-deployment/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/qt6-cross-platform-and-deployment/</guid><description>实测：同一个只链接 Core/Gui/Widgets 的 91546 字节 exe，`windeployqt --list` 报 107 个文件、真实部署只落地 60 个（79260474 字节）， 差的 47 个里 45 个是 `qtbase_*.qm`/`qtwebengine_*.qm`（本机只落了 32 个 `qt_*.qm`）、1 个是 `tls/qopensslbackend.dll`（源目录里明明存在）； `--list source/target/relative/mapping` 四种模式行数完全相同（107），`--dry-run` 一条不少地列出来但一个都不拷； `--no-plugins` 部署 44 个文件 75289796 字节，`platforms/` 整个目录消失； 唯一的告警原文是 `Warning: Cannot find any version of the dxcompiler.dll and dxil.dll.`； &quot;This application failed to start because no Qt platform plugin could be initialized…&quot; 这句在 Qt6Gui.dll 里是 **UTF-16 存储**（offset 9296920），`grep -a` 按 ASCII 数它是 0 次、按 UTF-16 数是 1 次； 同一版本号的 MinGW 与 MSVC 两套 Qt：`QMAKE_XSPEC` 分别是 win32-g++/win32-msvc，同名 Qt6Gui.dll 差 1880096 字节，MinGW 版依赖 libgcc_s_seh-1/libstdc++-6/libwinpthread-1，MSVC 版依赖 VCRUNTIME140(_1)/MSVCP140(_1) 和 11 个 api-ms-win-crt-*； 空 main() 用 `-lQt6Core` 指到 MSVC 的 lib 目录居然返回 0，说明&quot;链上了&quot;根本不代表 ABI 兼容。</description><pubDate>Fri, 16 Oct 2026 00:00:00 GMT</pubDate><category>Qt</category><category>部署</category><category>windeployqt</category><category>MinGW</category><category>MSVC</category></item><item><title>Qt 6 文件、设置与网络</title><link>https://wty.blogs.abrdns.com/posts/qt6-file-settings-and-network/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/qt6-file-settings-and-network/</guid><description>实测：Qt 6.9 的 QtCore 已经没有 GBK/GB18030/Big5 这些编码器（QStringDecoder(&quot;GBK&quot;).isValid()=0）， QTextStream 用 System 编码写&quot;模型视图Qt&quot;落盘 10 字节 C4 A3 D0 CD…（活动代码页 936），同一串 UTF-8 是 14 字节； 同一个 CRLF 文件 raw 读回 9 字节 md5=8c8f2ff0…、Text 读回 6 字节 md5=40c53c58…；Text 模式下 readAll 会吞掉结尾孤立的一个 \r 而 readLine 留着； 写 65536 字节未 flush 盘上立刻可见、写 4096 字节则盘上是 0；QSettings 的 ini 是 CRLF、组名里的斜杠写成 geometry\height、QDate 存成 @Variant 二进制； QNAM 发出的 GET 请求原文 161 字节且自带 accept-language: zh-CN,en,*；404/403/500 映射到 ContentNotFoundError(203)/ContentAccessDenied(201)/InternalServerError(401)，声明 gzip 给明文报 error=299； 本机 QSslSocket::supportsSsl()=1，但编译基线是 OpenSSL 3.0.7、运行时加载的是 /ucrt64/bin 的 3.5.8； 设一个连不上的 HttpProxy，127.0.0.1 目标照样成功、主机名目标才报 ProxyConnectionRefusedError(101)，走代理时请求行变成绝对 URL； QSQLITE 驱动 15 个特性位逐个可查、DATETIME 列读回来是 QString、QSqlQueryModel 的 flags=161 只读而 QSqlTableModel=163 可编辑。</description><pubDate>Fri, 16 Oct 2026 00:00:00 GMT</pubDate><category>Qt</category><category>网络</category><category>文件IO</category><category>QtSql</category><category>QSettings</category></item><item><title>Qt 6 主窗口体系与对话框</title><link>https://wty.blogs.abrdns.com/posts/qt6-main-window-and-dialogs/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/qt6-main-window-and-dialogs/</guid><description>实测：800x600 的 QMainWindow 五区几何是 menuBar 800x17 / toolBar 800x27 / 中央 628x492 @(86,44) / 左右 dock 各 80x36 / statusBar 800x22，dock 与中央之间固定被 6px 把手吃掉；藏掉 dock 中央从 514 涨到 600（+86），藏掉菜单栏只省 17px；saveState() 存 2 个 dock + 1 个工具栏是 177 字节且能 restore 成功；QDialog::exec() 在 6.9 返回的是 int（写 QDialog::Result 直接编译报错），done(3) 就返回 3；setModal(true)+show() 会让 activeModalWidget() 指向对话框，但在 exec 循环里 sendEvent 给父窗口的按钮三种模态全都拦不住（clicked 照样 =1）——模态拦的是平台输入路由，不是 Qt 的派发层；QSettings 写 5 个键 79 字节，remove() 后落盘 15 字节，但 setValue(key, QVariant()) 不删键而是写出一行 a=@Invalid()。</description><pubDate>Fri, 16 Oct 2026 00:00:00 GMT</pubDate><category>Qt</category><category>QMainWindow</category><category>QDialog</category><category>QSettings</category><category>模态</category></item><item><title>Qt 6 模型/视图与委托</title><link>https://wty.blogs.abrdns.com/posts/qt6-model-view-and-delegates/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/qt6-model-view-and-delegates/</guid><description>实测：20000 行 x 4 列，QTableWidget 填 42.5–45.3 ms、净增 17.5–17.9 MB（每格 228–234 B），同一份数据自定义 QVector&lt;Rec&gt; 模型只要 183–226 µs、0.64 MB（每格 8–9 B）；但 20000 行挂上 QTableView 后一次重绘只花 1309–1725 µs、只问 364 次 data()——首屏和总行数无关；delegate.sizeHint 的宽精确等于&quot;文本宽 + 6&quot;（0/1/2/4/8/16 字符全部命中），带勾选框再 +20 宽 +2 高；SizeHintRole=(0,40) 不会自动改行高（rowHeight 仍是 30），只有 resizeRowsToContents() 才变 41，而这一步在 20000 行上要 571 ms；fillRect 放在 QStyledItemDelegate::paint 之前会被 BackgroundRole 盖掉（实测 (1,1) 读到 (255,0,0) 而不是蓝）；QSortFilterProxyModel 按 DisplayRole 排 1..12 得到 &quot;1 10 11 12 2 3…&quot;，同列同序再调 sort() 是 0 µs 直接 return 所以光改 setSortRole 看不到效果；50000 行改一次过滤串 15.7–16.1 ms，挂上视图后同一次改动变 100.3 ms。</description><pubDate>Fri, 16 Oct 2026 00:00:00 GMT</pubDate><category>Qt</category><category>模型视图</category><category>委托</category><category>QModelIndex</category><category>QSortFilterProxyModel</category></item><item><title>Qt 6 绘图体系</title><link>https://wty.blogs.abrdns.com/posts/qt6-painting-system/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/qt6-painting-system/</guid><description>实测：QRectF(0,10.4,50,4) 落在第 10–13 行、10.5 落 11–14（四舍五入）；cosmetic 画笔 2px 在 scale(4) 下仍只占 2 个设备像素，而非 cosmetic 的 3px 笔被缩到 0.75px 时整条线消失；抗锯齿把 40x40 圆的边缘从 α=255 变成 244/243、非空像素 1240→1316，300 条线的绘制从 912 µs 涨到 2276 µs（2.5 倍）；dpr=2 的 QImage 上 fillRect(10,10,5,5) 真的落在设备像素 [20..29]x[20..29] 共 100 个；QT_SCALE_FACTOR=2 让 offscreen 屏幕几何从 800x800 变 400x400、devicePixelRatio 变 2.00，但 QFontMetrics 一个数都没变；QGraphicsView 一次 render 只画 12 个 item（10000 个里），视图放大 2 倍后降到 7 个、耗时从 370 µs 变 62 µs；不设 sceneRect 时 sceneRect() 是 O(n)（50000 item 要 12.3 ms），显式设了之后 0.30 µs。</description><pubDate>Fri, 16 Oct 2026 00:00:00 GMT</pubDate><category>Qt</category><category>QPainter</category><category>QGraphicsView</category><category>抗锯齿</category><category>高DPI</category></item><item><title>Qt 6 控件与布局</title><link>https://wty.blogs.abrdns.com/posts/qt6-widgets-and-layout/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/qt6-widgets-and-layout/</guid><description>实测：QPushButton 空文本 sizeHint 62x20、写&quot;确定&quot;变 80x20，QLineEdit sizeHint 210x22 但 minimumSizeHint 只有 18x20——差 11.7 倍，这就是它能被压扁的原因；600px 宽的 QHBoxLayout 里 stretch=(1,2,3) 精确分出 100/200/300，而 (0,0,1) 给按钮是 80/80/440、给裸 QWidget 是 0/0/600，卡住下限的是 minimumSizeHint 不是 stretch；QSizePolicy::Expanding 真实数值是 7、Ignored 是 13（不是文档顺序里的 6 和 7）；100px 的叶子控件外面套 4 层 margin=11 的布局，minimumSize 从 122x42 一路涨到 210x130，清成 0 后回到 100x20；不换行的 25 短语中文标签把布局顶成 1800px 宽，开了 wordWrap 后 minimumSizeHint 塌回 12x12；nextInFocusChain 的环里连 NoFocus/disabled/hidden 的控件都在；1000 个控件 addWidget 摊 4.05 µs/个、首次布局 25.6 µs/个。</description><pubDate>Fri, 16 Oct 2026 00:00:00 GMT</pubDate><category>Qt</category><category>控件</category><category>布局</category><category>sizeHint</category><category>焦点顺序</category></item><item><title>音频与媒体播放</title><link>https://wty.blogs.abrdns.com/posts/win-audio-media/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/win-audio-media/</guid><description>实测：本机 MCI 只有 5 个驱动、50 条扩展名映射，`type mpeg3audio` 稳定报 263（0.28–0.33 ms 就失败），m4a 按扩展名打开报 277 且要 53.3–86.3 ms；MCI 的 `play` 提交一次花 8.6–29.0 ms，位置推进前 1 秒只有 0.90–0.96 倍实时、之后 0.999–1.001；Media Foundation 首建 SourceReader 30.2 ms（同文件第 2 次 1.2–1.9 ms），60 秒 mp3 解成 PCM 用 107.4 ms＝559 倍实时，AAC 只给 4096 字节小缓冲而 MP3 给 86855 字节；XAudio2 建 master voice 26.8–29.7 ms 并一次吃掉 78 个内核句柄，source voice 单价 4.0–5.5 µs、200 个占 1.19 MB，未 Start 的 voice 提交 100 MB 缓冲仍返回 S_OK，但第 59/63 次提交就 `XAUDIO2_E_INVALID_CALL`；winmm 的音量读数是 0xFFFFFFFF / 65535（100%），同一台机器同一时刻 WASAPI 端点读回 −96.00 dB、scalar 0.0000、GetMute=1。</description><pubDate>Fri, 16 Oct 2026 00:00:00 GMT</pubDate><category>Win32</category><category>MCI</category><category>Media Foundation</category><category>XAudio2</category><category>WASAPI</category><category>winmm</category></item><item><title>对话框与公共控件</title><link>https://wty.blogs.abrdns.com/posts/win-dialog-control/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/win-dialog-control/</guid><description>实测：模态循环派发的是整条线程的消息——进模态前投给 owner 的 WM_USER+7 被对话框循环取走， 嵌套第二层模态里第一层的 WM_TIMER 照样 3→4→5→6 跳；对话框基线是 7×15 而 GetDialogBaseUnits 报 8×16； 回车属于 DM_GETDEFID 而不是焦点控件，两个 DEFPUSHBUTTON 时后写的赢且把前者的样式位清零； ListView 插 2000 行开重绘 597.5 ms、关掉 74.5 ms（8.02 倍），虚拟模式 100 万行只要 3.4 ms 和 32 KB； 钩子吞掉 WM_LBUTTONDOWN 后父窗口 WM_COMMAND 从 1 变 0，BM_CLICK 也被同一把钩子拦下； 对话框过程里 return DefDlgProcW(...) 是无限递归，进程连错误码都来不及打印就没了。</description><pubDate>Fri, 16 Oct 2026 00:00:00 GMT</pubDate><category>Windows</category><category>对话框</category><category>公共控件</category><category>ListView</category><category>子类化</category></item><item><title>注册表与配置存储</title><link>https://wty.blogs.abrdns.com/posts/win-registry-config/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/win-registry-config/</guid><description>实测：HKLM\SOFTWARE 的 64 位视图 71 个子键、32 位视图 56 个，而 32 位视图与字面 Wow6432Node 路径的末次写入时间 134344297879504256 一字不差（同一份数据的两个门）；HKCU\Software 三种视图都是 120 个子键，HKCU 不参与重定向； RegQueryValueExW 读 REG_SZ 报 14 字节而 RegGetValue 对同一个值报 146，RRF_RT_REG_EXPAND_SZ 不加 RRF_NOEXPAND 直接给 1630； 键名 4095 字符、值名 16385 字符、单值 4 MB 在本机都没被拒，往 HKLM 写一律 rc=5； RegNotifyChangeKeyValue 0.05–0.08 ms 就回来；HKCU 的 Run 键写值不需要提权，写→读回→删三步闭环走完，写完 1 秒后并没有启动； .qzdemo 只登记在 HKCU\Software\Classes，HKCR 立刻能读到，AssocQueryStringW 三条查询全 S_OK，但没注册的扩展名也返回 S_OK。</description><pubDate>Fri, 16 Oct 2026 00:00:00 GMT</pubDate><category>Windows</category><category>注册表</category><category>AppData</category><category>已知文件夹</category><category>文件关联</category></item><item><title>预处理、编译、汇编、链接</title><link>https://wty.blogs.abrdns.com/posts/build-four-stages-and-artifacts/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/build-four-stages-and-artifacts/</guid><description>实测：26 行源码预处理后变 2012 行/114685 字节（180 倍）；`-O2` 把 600 个函数从 62205 字节的 .o 压成 1480 字节（42 倍），可同一份小文件的 .o 反而比 -O0 大 29%——因为段从 7 个变成 10 个；`-ffinite-math-only` 把运行时的 `isnan()` 折成恒 0，而 `-Ofast` 走的是另一条路：它先把 `x/x` 简化成常量 1，NaN 根本不再产生。；`.txt` 后缀会被当成链接输入并以退出码 0 静默产出零个文件。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>编译</category><category>构建</category><category>GCC</category><category>MinGW</category></item><item><title>目标文件、段与符号表</title><link>https://wty.blogs.abrdns.com/posts/build-object-files-sections-symbols/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/build-object-files-sections-symbols/</guid><description>实测：1 MiB 未初始化数组和 1 字节的 .o 一样大（都是 748 字节，.bss 不占文件一字节），而 1 MiB 已初始化数组的 .o 是 1049324 字节；MinGW 的 .exe 尾部留着整套 COFF 符号表，strip 前后 97456→52224、157541→54272；只有弱定义时链接直接报 undefined reference；`-fno-common` 下 `int shared;` 是强符号 `B`，`-fcommon` 下才是 `C`。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>目标文件</category><category>COFF</category><category>符号表</category><category>nm</category><category>objdump</category></item><item><title>数组与字符串</title><link>https://wty.blogs.abrdns.com/posts/c-arrays-and-strings/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/c-arrays-and-strings/</guid><description>数组就是一段连续内存，这句话能解释 C 里九成的数组 bug。地址实测、退化规则、\0 终止符、strncpy 的陷阱，以及越界访问为什么&quot;看起来能用&quot;。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>C语言</category><category>数组</category><category>字符串</category></item><item><title>语言骨架：变量、类型与运算符</title><link>https://wty.blogs.abrdns.com/posts/c-basics-types-operators/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/c-basics-types-operators/</guid><description>C 的语法看着小，坑集中在三处：类型的真实宽度、混合运算的隐式转换、以及把&quot;求值顺序&quot;当成&quot;优先级&quot;。所有数字都在本机 MinGW GCC 13.1.0 上实测。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>C语言</category><category>类型系统</category><category>基础</category></item><item><title>流程控制与函数</title><link>https://wty.blogs.abrdns.com/posts/c-control-flow-functions/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/c-control-flow-functions/</guid><description>switch 的 fallthrough 是默认行为、空括号的函数声明不检查参数、尾递归优化在 C 里根本没有保证——这一节把流程控制和函数边界的规则一次说清，所有结论都有编译器和反汇编作证。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>C语言</category><category>函数</category><category>流程控制</category></item><item><title>动态内存与对象生命周期</title><link>https://wty.blogs.abrdns.com/posts/c-dynamic-memory-and-lifetime/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/c-dynamic-memory-and-lifetime/</guid><description>栈、堆、静态区的真实地址分布，malloc 与 calloc 的差别值一次 memset，内存池比逐个分配快在哪，以及在没有 ASAN 的工具链上用一张账本抓泄漏。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>C语言</category><category>内存管理</category><category>性能</category></item><item><title>文件与流式 IO</title><link>https://wty.blogs.abrdns.com/posts/c-file-and-stream-io/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/c-file-and-stream-io/</guid><description>文本模式在 Windows 上到底改了什么、r+ 读完不 fseek 就写会静默丢数据、feof 为什么必须放在读之后判断，以及 C11 的 x 模式在本机 msvcrt 上根本不可用。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>C语言</category><category>文件IO</category><category>标准库</category></item><item><title>指针与内存模型</title><link>https://wty.blogs.abrdns.com/posts/c-pointers-and-memory/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/c-pointers-and-memory/</guid><description>指针算术的真实语义、const 的传递规则为什么只给警告、减法比较器怎么把 qsort 排错、释放后读为什么不崩反而更危险，以及返回栈地址在本机如何当场段错误。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>C语言</category><category>指针</category><category>内存管理</category></item><item><title>预处理与编译四阶段</title><link>https://wty.blogs.abrdns.com/posts/c-preprocessor-and-build-stages/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/c-preprocessor-and-build-stages/</guid><description>一行源码变成 1102 行、宏的括号为什么能决定成败、目标文件里的符号表怎么看、头文件守卫漏掉会报什么错——把&quot;编译&quot;拆成四步看清楚。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>C语言</category><category>预处理</category><category>编译原理</category></item><item><title>受限环境与 volatile</title><link>https://wty.blogs.abrdns.com/posts/c-restricted-environment-and-volatile/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/c-restricted-environment-and-volatile/</guid><description>volatile 到底保证什么——两条反汇编指令说清；忙等待为什么会被整个删掉、没有堆怎么分配内存、栈预算怎么量，以及 -Os 比 -O2 小在哪。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>C语言</category><category>嵌入式</category><category>volatile</category></item><item><title>标准库常用设施</title><link>https://wty.blogs.abrdns.com/posts/c-standard-library/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/c-standard-library/</guid><description>string.h 的长度语义、memcpy 与 memmove 在重叠时的真实差异、atoi 与 strtol 的分水岭、errno 什么时候能读，以及 RAND_MAX 只有 32767 这件事。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>C语言</category><category>标准库</category><category>字符串</category></item><item><title>结构体、联合体与枚举</title><link>https://wty.blogs.abrdns.com/posts/c-struct-union-enum/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/c-struct-union-enum/</guid><description>sizeof 为什么比你算的大、字段顺序值几字节、填充字节怎么让 memcmp 骗过你、位域和联合体的实现定义边界，以及柔性数组的正确用法。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>C语言</category><category>结构体</category><category>内存布局</category></item><item><title>未定义行为与严格别名</title><link>https://wty.blogs.abrdns.com/posts/c-undefined-behavior-and-aliasing/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/c-undefined-behavior-and-aliasing/</guid><description>同一份代码在 -O0 给出 2、-O2 给出 1——严格别名规则怎么让编译器生成&quot;错&quot;代码，以及有符号溢出和判空被删背后的同一套逻辑：编译器按假设优化，而不是按你的意图。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>C语言</category><category>未定义行为</category><category>优化</category></item><item><title>可变参数与复杂声明</title><link>https://wty.blogs.abrdns.com/posts/c-variadic-and-declarations/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/c-variadic-and-declarations/</guid><description>stdarg 的三条硬规则（类型靠约定、float 必按 double 读、va_copy 才能遍历两遍），复杂声明的读法口诀，以及 _Generic 为什么匹配不到 const char * 分支。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>C语言</category><category>stdarg</category><category>声明</category></item><item><title>原子操作与内存序</title><link>https://wty.blogs.abrdns.com/posts/conc-atomics-and-memory-order/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/conc-atomics-and-memory-order/</guid><description>实测：同一个 SB 装配下，relaxed 的 120 万轮里有 54%–63% 出现 r1==0&amp;&amp;r2==0 的违例，把内存序换成 seq_cst 后两次各 120 万轮都是 0；seq_cst 存是 `xchg`（5.71ns），relaxed 存是 `mov`（0.26ns），而 `lock addq` 无论什么序都一个价；16 字节 atomic 在 MinGW 上不加 -latomic 直接链不过，加了之后 is_lock_free=0。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>并发</category><category>原子操作</category><category>内存序</category></item><item><title>条件变量与等待通知</title><link>https://wty.blogs.abrdns.com/posts/conc-condition-variable/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/conc-condition-variable/</guid><description>实测：判断写在锁外会真的永久卡死（看门狗 3 秒超时、CPU 采样 0）；单条件变量配 notify_one 在小缓冲上死锁，同场景 notify_all 要 8.5 秒而双条件变量只要 1.6 秒；wait_for(10µs) 实际睡 15.1 毫秒。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>并发</category><category>条件变量</category><category>生产者消费者</category></item><item><title>协程与异步模型</title><link>https://wty.blogs.abrdns.com/posts/conc-coroutines-and-async-models/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/conc-coroutines-and-async-models/</guid><description>实测：C++20 协程的 resume 只要 3.56 纳秒、帧 64 字节，创建+销毁 10 万个协程 15.6 毫秒；Win32 Fiber 每次切换 41 纳秒但每个协程实占 32172 字节——10 万个 Fiber 直接吃掉 3069.84 MB 提交内存，比协程多 412 倍；线程是 120.8 微秒创建 + 37 KB。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>并发</category><category>协程</category><category>Fiber</category><category>IOCP</category></item><item><title>无锁结构</title><link>https://wty.blogs.abrdns.com/posts/conc-lock-free/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/conc-lock-free/</guid><description>实测：手工排出交错的 ABA 演示里，A 的 CAS 返回&quot;成功&quot;并把早已弹走的节点接回链表；4 线程随机对拍 30 万步，无锁栈重复取走 0 个（结构正确）却比有锁栈慢 2.07 倍（58.5ms vs 28.3ms），而单线程无竞争时它反而快 1.45 倍（12.59 vs 18.25 ns/次）。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>并发</category><category>无锁</category><category>CAS</category></item><item><title>互斥锁与临界区</title><link>https://wty.blogs.abrdns.com/posts/conc-mutex-and-critical-section/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/conc-mutex-and-critical-section/</guid><description>实测：无保护的自增丢掉 70.7% 的更新，但 -Wall -Wextra 一声不响、MinGW 连 -fsanitize=thread 都链不上；锁的 uncontended 单价 16.65ns，把计算移出锁外吞吐快 5.5 倍；try_lock_for(10µs) 实际每次卡 15.9 毫秒。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>并发</category><category>互斥锁</category><category>死锁</category></item><item><title>并发设计模式</title><link>https://wty.blogs.abrdns.com/posts/conc-patterns/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/conc-patterns/</guid><description>实测：std::async 每次派生 53.3 微秒，500 个 0.1ms 任务不 get 只靠 future 析构就花 110.3ms（等于串行）；launch::deferred 的任务在 get 之前一次都没执行；actor 邮箱逐条投递 0.091µs/条、攒 1000 条一批投 0.023µs/条；COW 快照要读段长到 800 次累加才反超 mutex（1.70x）。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>并发</category><category>future</category><category>无锁快照</category></item><item><title>pthread 与 std::thread 对照</title><link>https://wty.blogs.abrdns.com/posts/conc-pthread-vs-std-thread/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/conc-pthread-vs-std-thread/</guid><description>实测：MinGW 上 sizeof(std::thread)=8 且 native_handle() 与 pthread_self 是同一个值；PTHREAD_CREATE_DETACHED 在这里等于 4 而不是 1；pthread_setschedparam(SCHED_FIFO) 返回 129；三种生命周期误用的退出码都是 0x00000003。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>并发</category><category>pthread</category><category>std::thread</category></item><item><title>同步工具族</title><link>https://wty.blogs.abrdns.com/posts/conc-sync-primitives/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/conc-sync-primitives/</guid><description>实测：MinGW 上 shared_mutex 无竞争单价是 std::mutex 的 5–5.7 倍，8 线程纯读时反而慢 9 倍，读临界区长到 1600 次累加才追平；自旋锁无竞争比 mutex 快 45%，多来 4 个可运行线程就反过来慢 3.6 倍；call_once 已完成路径只要 3.11 纳秒。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>并发</category><category>读写锁</category><category>信号量</category></item><item><title>任务队列与线程池</title><link>https://wty.blogs.abrdns.com/posts/conc-task-queue-and-thread-pool/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/conc-task-queue-and-thread-pool/</guid><description>实测：100 万个待执行任务吃掉 35.30MB（每任务 36 字节）；200 个 1ms 的 CPU 任务在 P=8 时 38.1ms 跑完、P=12 反而退回 50.9ms，而 120 个阻塞任务加到 16 线程只用 121.6ms；优雅关闭能兑现&quot;一个不丢&quot;（2000 个里 1865 个还在排队），detach 之后 400 个任务只完成 0 个。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>并发</category><category>线程池</category><category>任务队列</category></item><item><title>线程与进程模型</title><link>https://wty.blogs.abrdns.com/posts/conc-threads-vs-processes/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/conc-threads-vs-processes/</guid><description>实测：唤醒一次线程交接 11.35 微秒，原子自旋交接 61 纳秒，同一个逻辑处理器塞 2 个线程吞吐只涨 1%；一个空闲线程 37KB 提交内存，一个空进程 3.83MB 加 84 个句柄、启动 16.74 毫秒。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>并发</category><category>线程</category><category>进程</category></item><item><title>类与封装</title><link>https://wty.blogs.abrdns.com/posts/cpp-classes-and-encapsulation/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/cpp-classes-and-encapsulation/</guid><description>空类为什么占 1 字节、成员按声明顺序构造而不是初始化列表顺序、移动构造少写一个 noexcept 就让 vector 扩容多拷一千次——类的骨架规则一次讲清。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>C++</category><category>类</category><category>RAII</category></item><item><title>STL 容器与迭代器</title><link>https://wty.blogs.abrdns.com/posts/cpp-containers-and-iterators/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/cpp-containers-and-iterators/</guid><description>vector 每次翻倍的实测序列、reserve 把 15 次分配变成 1 次、list 遍历比 vector 慢 16.7 倍、emplace_back 省掉的正好是那 5 次移动——容器选型的数字版。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>C++</category><category>STL</category><category>容器</category></item><item><title>异常与错误处理策略</title><link>https://wty.blogs.abrdns.com/posts/cpp-exception-and-error-strategy/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/cpp-exception-and-error-strategy/</guid><description>一次 throw+catch 实测 4 微秒、比返回码慢十倍；析构函数抛异常和 noexcept 里抛异常都在编译期就被 -Wterminate 点出来；expected 的开销只有 24 字节。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>C++</category><category>异常</category><category>错误处理</category></item><item><title>从 C 到 C++：引用、const 与重载</title><link>https://wty.blogs.abrdns.com/posts/cpp-from-c-references-const-overloading/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/cpp-from-c-references-const-overloading/</guid><description>同一份源码在 gcc 和 g++ 下结果不同——字符常量的类型、const 的链接性、f() 的含义、指定初始化的顺序。这些差异不是风格问题，是编译期就分岔的语义。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>C++</category><category>C++基础</category><category>引用</category><category>重载</category></item><item><title>继承与多态</title><link>https://wty.blogs.abrdns.com/posts/cpp-inheritance-and-polymorphism/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/cpp-inheritance-and-polymorphism/</guid><description>构造函数里调虚函数会静默降级成基类版本、虚函数的默认参数按静态类型取、对象切片把 72 字节压成 8 字节——继承的规则一条条用输出验证。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>C++</category><category>继承</category><category>多态</category></item><item><title>C++11 到 C++23 特性时间线</title><link>https://wty.blogs.abrdns.com/posts/cpp-modern-standards-timeline/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/cpp-modern-standards-timeline/</guid><description>每个版本到底解决了什么问题，以及一份本机 g++ 13.1.0 的实测支持矩阵——std::expected 已经能用，而 std::print、mdspan、deducing this 还不行。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>C++</category><category>版本特性</category><category>编译器支持</category></item><item><title>移动语义与完美转发</title><link>https://wty.blogs.abrdns.com/posts/cpp-move-semantics-and-forwarding/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/cpp-move-semantics-and-forwarding/</guid><description>std::move 一个字节都不搬、被移动对象必须处于&quot;有效但未定&quot;状态、return std::move(local) 会让复制消除退化成一次移动——全部用计数器实测。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>C++</category><category>移动语义</category><category>完美转发</category></item><item><title>对象模型与内存布局</title><link>https://wty.blogs.abrdns.com/posts/cpp-object-model-and-layout/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/cpp-object-model-and-layout/</guid><description>两条反汇编指令看清虚函数调用的代价——mov (%rcx),%rax 加 jmp *(%rax)；多继承下同一个对象的两个基类指针地址不同；dynamic_cast 比 static_cast 慢 3.7 倍。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>C++</category><category>对象模型</category><category>虚函数</category></item><item><title>RAII 与资源管理实战</title><link>https://wty.blogs.abrdns.com/posts/cpp-raii-and-resource-management/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/cpp-raii-and-resource-management/</guid><description>构造中途抛异常时哪些资源会被释放、手写一个 20 行的 scope guard、非虚析构 delete 让派生类析构次数为 0，以及 rule of zero 到底怎么落地。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>C++</category><category>RAII</category><category>资源管理</category></item><item><title>智能指针与所有权</title><link>https://wty.blogs.abrdns.com/posts/cpp-smart-pointers-and-ownership/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/cpp-smart-pointers-and-ownership/</guid><description>unique_ptr 真的是零开销吗、make_shared 省掉的那次分配是什么、循环引用怎么把对象留在内存里——用 sizeof 和 new 计数器实测。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>C++</category><category>智能指针</category><category>RAII</category></item><item><title>常用标准库入门</title><link>https://wty.blogs.abrdns.com/posts/cpp-standard-library-basics/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/cpp-standard-library-basics/</guid><description>30 万次查找实测 map 比 unordered_map 慢 10 倍、sorted vector 二分反而快过 std::set、operator[] 会偷偷插入、reserve 让 push_back 快 2.4 倍——用数字建立选型直觉。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>C++</category><category>标准库</category><category>性能</category></item><item><title>模板与泛型</title><link>https://wty.blogs.abrdns.com/posts/cpp-templates-and-concepts/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/cpp-templates-and-concepts/</guid><description>完美转发到底省掉多少次拷贝（实测 100 次调用零拷贝）、函数模板为什么不能偏特化、以及一个反常识结论：concepts 的报错行数比无约束版更多，但它把错误停在了调用点。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>C++</category><category>模板</category><category>concepts</category></item><item><title>关系模型与 SQL 入门：把表、主键、外键放到机器上量一遍</title><link>https://wty.blogs.abrdns.com/posts/db-relational-model-and-constraints/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/db-relational-model-and-constraints/</guid><description>实测：VARCHAR(10) 存进 20 字符照样成功；TEXT 主键允许两个 NULL，INTEGER PRIMARY KEY 就是 rowid；外键默认 OFF，孤儿数据留着而 integrity_check 仍然返回 ok；10 万行订单反范式化多花 1.83 倍字节、改名要动 11643 行而不是 116 行；逐条 autocommit 比单事务慢 717–1053 倍。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>数据库</category><category>关系模型</category><category>SQL</category><category>SQLite</category><category>Qt SQL</category></item><item><title>GDB 实战：断点、栈帧与崩溃现场</title><link>https://wty.blogs.abrdns.com/posts/dbg-gdb-breakpoints-and-frames/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/dbg-gdb-breakpoints-and-frames/</guid><description>实测：同一个 -O2 二进制，-g1 只比 -g0 大 1820 字节（+2.4%）却足够 addr2line 反查到 crash.c:13；10000 次命中的软件断点摊到 106µs/次，条件从不成立反而 151µs，软件观察点 6.0ms/次（比硬件观察点贵 46 倍）；MinGW GDB 11.2 的 record 报&quot;架构不支持&quot;、scheduler-locking 不支持，run 之前设的 watchpoint 跑满 10000 次写而一次都不触发。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>调试</category><category>GDB</category><category>调试信息</category><category>崩溃取证</category></item><item><title>日志与可定位性设计：级别、刷盘与真实成本</title><link>https://wty.blogs.abrdns.com/posts/dbg-log-and-observability/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/dbg-log-and-observability/</guid><description>实测：落盘字节 = ⌊已写字节 ÷ 缓冲区大小⌋ × 缓冲区大小——写满 3001 行(113728 字节)后崩溃，4KB 缓冲留 2918 行(110592=27×4096)，1MB 缓冲留 0 行；级别短路放在格式化之前是 0.2ns/行，放在之后是 181.2ns/行（900 倍）；同一行落在 1MB 缓冲/默认 4KB/每行 fflush 上分别是 260/769/8195 ns；行缓冲 64 字节时 snprintf 静默截断而返回值照报 91；全局锁+共享 FILE 比每线程独立文件贵 8.5 倍；文本日志 zlib 后只剩 4.9%–9.5%。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>日志</category><category>可观测性</category><category>刷盘</category><category>性能</category></item><item><title>进阶结构专题</title><link>https://wty.blogs.abrdns.com/posts/ds-advanced-structures/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/ds-advanced-structures/</guid><description>并查集只加&quot;按秩合并&quot;就从 5091ms 掉到 4.2ms（1200 倍），再加路径压缩反而没变快；线段树懒标记与朴素实现查询结果逐位相同；LRU 用 list+哈希 100 万次操作 134ms。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>数据结构</category><category>并查集</category><category>线段树</category></item><item><title>线性表：数组与链表</title><link>https://wty.blogs.abrdns.com/posts/ds-arrays-and-linked-lists/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/ds-arrays-and-linked-lists/</guid><description>中间插入 10 万次 list 比 vector 快 216 倍，可反转整个表时 vector 又赢 18 倍，遍历差 33 倍——&quot;数组好还是链表好&quot;没有答案，只有工作负载的答案。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>数据结构</category><category>链表</category><category>数组</category></item><item><title>复杂度分析与大 O</title><link>https://wty.blogs.abrdns.com/posts/ds-complexity-analysis/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/ds-complexity-analysis/</guid><description>n 翻倍耗时到底变几倍、二分在 100 万元素上只要 20 次比较、vector 扩容的 131071 次搬移怎么摊成 1.31、同样 O(n²) 的两种写法差 13 倍——用数字代替直觉。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>数据结构</category><category>算法</category><category>复杂度</category></item><item><title>动态规划</title><link>https://wty.blogs.abrdns.com/posts/ds-dynamic-programming/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/ds-dynamic-programming/</guid><description>斐波那契 n=40 朴素递归 196.9ms vs 迭代 0.0001ms；背包一维滚动写成正序时，有 23% 的随机用例结果&quot;碰巧正确&quot;；二维降到滚动数组是 62.5MB 变 31KB。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>数据结构</category><category>动态规划</category><category>算法</category></item><item><title>图的存储与遍历</title><link>https://wty.blogs.abrdns.com/posts/ds-graph-storage-and-traversal/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/ds-graph-storage-and-traversal/</guid><description>200 万条边的实测：CSR 建图比 vector&lt;vector&lt;int&gt;&gt; 快 7.4 倍、内存省 3 倍；邻接矩阵要 596MB 而邻接表只要 7.6MB；递归 DFS 在 10 万层崩溃而迭代版跑完 500 万层。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>数据结构</category><category>图</category><category>遍历</category></item><item><title>贪心、分治与回溯</title><link>https://wty.blogs.abrdns.com/posts/ds-greedy-divide-conquer-backtracking/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/ds-greedy-divide-conquer-backtracking/</guid><description>4000 组随机币制实测贪心找零有 16.3% 的金额算错；N 皇后位运算版快 10.7 倍且解数与已知值完全一致；区间调度换成&quot;按开始时间&quot;就从 3 变 1。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>数据结构</category><category>贪心</category><category>回溯</category></item><item><title>哈希表与冲突处理</title><link>https://wty.blogs.abrdns.com/posts/ds-hash-tables/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/ds-hash-tables/</guid><description>200 万次查找实测 unordered_map 110.6ms、sorted vector 542.7ms、map 2512.3ms；键步长为 4 时低位散列只用 25% 的桶；空桶率 21.6% 才是正常状态。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>数据结构</category><category>哈希表</category><category>散列</category></item><item><title>堆与优先队列</title><link>https://wty.blogs.abrdns.com/posts/ds-heaps-and-priority-queues/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/ds-heaps-and-priority-queues/</guid><description>手写堆的两个比较方向都写反了、30 万次随机操作对拍才抓出来；双堆求流式中位数比每次重算快 3862 倍；k 路归并理论更优却比&quot;拼接再排序&quot;慢 43%。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>数据结构</category><category>堆</category><category>优先队列</category></item><item><title>排序算法全族</title><link>https://wty.blogs.abrdns.com/posts/ds-sorting-algorithms/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/ds-sorting-algorithms/</guid><description>500 万元素实测：基数排序 58.9ms 完胜 std::sort 的 329ms，三路快排在全部相等时只要 4.2ms；稳定性测试本身也容易做错——把下标当第二键会让快排&quot;看起来稳定&quot;。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>数据结构</category><category>排序</category><category>算法</category></item><item><title>栈与队列</title><link>https://wty.blogs.abrdns.com/posts/ds-stacks-and-queues/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/ds-stacks-and-queues/</guid><description>循环队列为什么必须少用一个槽位（附错公式的实测后果）、单调队列把滑动窗口从 53.8ms 压到 2.74ms、最小栈与双栈表达式求值，以及用随机数据交叉验证单调栈的正确性。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>数据结构</category><category>栈</category><category>队列</category></item><item><title>串与模式匹配</title><link>https://wty.blogs.abrdns.com/posts/ds-string-matching/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/ds-string-matching/</guid><description>KMP 的 next 数组怎么推、2000 组随机用例对拍验证、AC 自动机比逐个 KMP 快 43 倍（30699 次命中完全一致），以及 strlen 放进循环条件在 -O0 和 -O2 下差 1900 倍与 9 倍。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>数据结构</category><category>字符串</category><category>KMP</category></item><item><title>树：二叉树、BST 与堆</title><link>https://wty.blogs.abrdns.com/posts/ds-trees-bst-and-heaps/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/ds-trees-bst-and-heaps/</guid><description>同样 1 万个数，有序输入让 BST 高度变成 10000、随机输入只有 34；make_heap 只比逐个 push 快 1.2 倍；取最大 10 个元素 partial_sort 比全排序快 100 倍。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>数据结构</category><category>树</category><category>堆</category></item><item><title>Code Review：能让机检的都别留给眼睛</title><link>https://wty.blogs.abrdns.com/posts/engineering-code-review-practice/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/engineering-code-review-practice/</guid><description>实测把 12 种坏 frontmatter 喂给本仓库现有的门禁，机器抓住 8 种、放过 4 种，其中&quot;date 带时间&quot;会让发布日静默退一天；而 12 种注入 + 57 篇文章全量校验只花 0.58 秒（3 次中位）——评审预算该花在哪，数字很清楚。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>工程实践</category><category>Code Review</category><category>静态检查</category></item><item><title>README 是可执行文件</title><link>https://wty.blogs.abrdns.com/posts/engineering-doc-and-readme/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/engineering-doc-and-readme/</guid><description>把 README 的每一句声明当断言跑一遍——6 条主要断言全对，唯一说谎的地方是 `package.json` 里第 4 个脚本 `npm run check`：文档一次没提、CI 也一次没跑。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>工程实践</category><category>文档</category><category>README</category></item><item><title>分支模型与历史整理：先把只读的路走稳</title><link>https://wty.blogs.abrdns.com/posts/engineering-git-advanced/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/engineering-git-advanced/</guid><description>实测一个 64 提交的回归引入点，`git bisect run` 只判定 6 个提交、9.5 秒定位——但它的前置条件比命令本身重要得多：产物入库会让整条路随机罢工。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>工程实践</category><category>Git</category><category>分支策略</category></item><item><title>代码风格：能让工具管的，就别用人管</title><link>https://wty.blogs.abrdns.com/posts/engineering-style-naming-and-formatting/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/engineering-style-naming-and-formatting/</guid><description>让工具管格式、人管意图——实测一个纯格式化提交会劫走 86 行文件里 21 行的 blame 归属（`git diff -w` 只能救回 2 行），而它改动前后的机器码 162 条指令逐字节相同。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>工程实践</category><category>代码风格</category><category>clang-format</category></item><item><title>单元测试：覆盖率考的是输入，变异考的是断言</title><link>https://wty.blogs.abrdns.com/posts/engineering-unit-test-and-mock/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/engineering-unit-test-and-mock/</guid><description>实测 6 个纯函数、30 条断言拿到 100% 行覆盖、92.86% 分支覆盖，但 11 个人为植入的缺陷只杀掉 7 个（63.6%）；补 3 个测试后覆盖率只涨 0.47 个百分点，变异杀死率涨 27.3 个百分点（10/11）。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>工程实践</category><category>单元测试</category><category>覆盖率</category><category>变异测试</category></item><item><title>以太网、ARP 与交换机</title><link>https://wty.blogs.abrdns.com/posts/net-ethernet-arp-switch/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/net-ethernet-arp-switch/</guid><description>实测：本机 ARP 表在 /24 里学到 69 个邻居；一次失败解析发出两条间隔 17 微秒的 who-has 后邻居状态变 Unreachable；9000 字节 MTU 的边界是 8972 能过、8973 报&quot;需要拆分数据包但是设置 DF&quot;；12 秒混杂抓包里出现 0 个 802.1Q 帧和 4 个 255.255.255.255 广播。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>网络</category><category>以太网</category><category>ARP</category></item><item><title>IP、子网与路由</title><link>https://wty.blogs.abrdns.com/posts/net-ip-routing-and-icmp/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/net-ip-routing-and-icmp/</guid><description>实测：本机 40 条 IPv4 路由里 21 条是 /32，五个子网广播地址由&quot;IP &amp; ~掩码&quot;手算后与内核路由逐条对上；ICMP 差错报文被内核截到 576 字节（正好等于 netsh 里的&quot;最小 MTU&quot;）；突发 1000 个 UDP 包只生成 194 条端口不可达；ttl=1 的探测在本机拿到的是 type=0 回包，抓包里 0 条 type=11。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>网络</category><category>IP</category><category>子网</category><category>路由</category><category>ICMP</category></item><item><title>分层模型与抓包入门</title><link>https://wty.blogs.abrdns.com/posts/net-layer-model-and-capture/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/net-layer-model-and-capture/</guid><description>本机 Npcap 实测：1 字节应用数据在回环上是 45 字节帧、在 9000 MTU 链路上封装成 9000 字节帧（MSS 8960）；一次完整 TCP 生命周期只用 9 帧 452 微秒；非管理员权限也能直接调 wpcap.dll 抓包。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>网络</category><category>抓包</category><category>Npcap</category></item><item><title>TCP 连接管理</title><link>https://wty.blogs.abrdns.com/posts/net-tcp-connection-management/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/net-tcp-connection-management/</guid><description>实测：本机 TIME_WAIT 只停留 119–120 秒（不是资料里常见的 240 秒）；backlog=5 时 40 条 SYN 里只有 5 条拿到 SYN/ACK，另外 35 条被 RST，而应用要等 2.03–2.07 秒才收到 10061；服务端带着未读数据 close 会让对端拿到 10054 而不是 EOF，且两侧都不产生 TIME_WAIT；每请求新建连接的成本是复用的 5.9 倍；保活探测实测周期 3.01 秒、对端 19 微秒内用 SACK 确认那 1 个字节。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>网络</category><category>TCP</category><category>握手</category><category>TIME_WAIT</category><category>keepalive</category></item><item><title>内存分层与地址空间</title><link>https://wty.blogs.abrdns.com/posts/os-memory-layout-and-hierarchy/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/os-memory-layout-and-hierarchy/</guid><description>实测：申请 1 字节也占 4096 字节，粒度 65536 只管基址对齐；一个空进程 107 个区域、提交 9.8MB 却&quot;仅保留&quot;4136.8MB；32MB 匿名内存提交时缺页 0 次，冷触碰 1147 纳秒/页、热触碰 12 纳秒/页（95 倍）；malloc(1) 实付 18.1 字节，free 20 万块后仍多占 1.71MB。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>操作系统</category><category>虚拟内存</category><category>页缓存</category><category>内存分配器</category><category>局部性</category></item><item><title>进程、线程与上下文切换</title><link>https://wty.blogs.abrdns.com/posts/os-process-and-thread/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/os-process-and-thread/</guid><description>实测：主线程栈的已提交窗口 20480 字节、下面紧一页 PAGE_GUARD，递归 200 层后窗口变 839680 字节、缺页计数 +205，护栏页跟着往下跑；一次纤程切换 42.8 纳秒、100 万次内核上下文计数只 +11；Sleep(0) 每次让出恰好 1 次上下文切换（0.90–1.11 次/调用）。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>操作系统</category><category>进程</category><category>线程</category><category>TEB</category><category>上下文切换</category><category>纤程</category></item><item><title>调度算法与实时性</title><link>https://wty.blogs.abrdns.com/posts/os-scheduling-and-realtime/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/os-scheduling-and-realtime/</guid><description>实测：NORMAL 进程类里 HIGHEST 的绝对优先级是 10、TIME_CRITICAL 恒为 15；同一颗逻辑处理器上 LOWEST 对 HIGHEST 只能拿到 0.25% 的迭代，短线程的完成时间从 29.4 毫秒被压到 216.1 毫秒；Sleep(5) 40 次中位 15.67 毫秒；SetPriorityClass(REALTIME) 返回 TRUE、lasterr=0，而实际进程类是 0x80（HIGH）。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>操作系统</category><category>调度</category><category>优先级</category><category>实时</category><category>优先级反转</category></item><item><title>操作系统在做什么</title><link>https://wty.blogs.abrdns.com/posts/os-what-kernel-does/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/os-what-kernel-does/</guid><description>实测：一次系统调用在机器上就是 24 个字节（mov r10,rcx + mov eax,服务号 + syscall）；读 gs:[0x40] 拿 PID 只要 1.5 纳秒，而最便宜的陷入是 82.4 纳秒；0x7FFE0000 那 4KB 只读页里 +0x008 每 100 纳秒进 1、+0x320 每 15.57 毫秒进 1，这就是 Sleep(1) 实测中位 15.18 毫秒的来源。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>操作系统</category><category>系统调用</category><category>内核态</category><category>KUSER_SHARED_DATA</category><category>Win32</category></item><item><title>Qt 6 事件循环与事件处理</title><link>https://wty.blogs.abrdns.com/posts/qt6-event-loop-and-event-handling/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/qt6-event-loop-and-event-handling/</guid><description>实测：一次 sendEvent 派发 49–55ns，postEvent 入队加排空 290ns（5.9 倍）；忙等 200ms 错过 20 个 10ms tick、事后只补发 1 个事件（错过的 tick 不补帧）；VeryCoarseTimer 把 300ms 变成 1000.9ms（3.3 倍），CoarseTimer 的 50ms 实测 62.6ms（+25%）；Windows 的 15.6ms tick 困不住 Qt——Sleep(1) 实测 14.9ms，而 QTimer(1ms) 是 1.05ms，因为有活动定时器时进程分辨率被抬到 1ms（tick 里 Sleep(1)=1.63ms）；槽里调 processEvents() 每层重入吃 13.3KB 栈，60 层就是 786KB；1000 次 update() 只换来 1 次 Paint，500 次 resize() 却产生 499 个 Resize 事件。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>Qt</category><category>事件循环</category><category>QTimer</category><category>processEvents</category></item><item><title>Qt 6 框架总览与工程搭建</title><link>https://wty.blogs.abrdns.com/posts/qt6-framework-overview-and-project-setup/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/qt6-framework-overview-and-project-setup/</guid><description>实测：Q_OBJECT 让 108 行头文件膨胀成 1109 行 C++、单 TU 编译 +26%，但对象体积一字节不加；忘跑 moc 的签名是 `undefined reference to &apos;vtable for Widget&apos;`；CMAKE_PREFIX_PATH 不写，CMake 会静默挑中另一套 Qt 再在链接期炸出 3 条 __imp_ 未定义引用；w.show() 返回 0.0ms 且一次 Paint 都没派发。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>Qt</category><category>CMake</category><category>moc</category></item><item><title>Qt 6 信号槽与元对象系统</title><link>https://wty.blogs.abrdns.com/posts/qt6-signal-slot-and-meta-object-system/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/qt6-signal-slot-and-meta-object-system/</guid><description>实测：不带类型码前缀的裸字符串 connect 恒失败并报 `Use the SIGNAL macro to bind ...`；宏式 connect 比函数指针版贵 2.7 倍、字符串版贵 4.0 倍、拼错名字再贵 4.6 倍；emit 每多一个连接 +15–22ns，跨线程入队是同线程的 15–21 倍；`QMetaObject::Connection` 在 6.9 已无 `isValid()`；`connectSlotsByName` 重复调用会把同一个槽接两遍；`property()` 比直接 getter 慢 120 倍且代价随属性在表里的**位置**线性上涨。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>Qt</category><category>信号槽</category><category>元对象</category><category>Q_PROPERTY</category></item><item><title>GDI 绘图与双缓冲</title><link>https://wty.blogs.abrdns.com/posts/win-gdi/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/win-gdi/</guid><description>实测：同样 120 个矩形，画在窗口 DC 上每个 16.9 微秒，画在内存 DC 上每个 1.3 微秒（13 倍），双缓冲把一帧从 2.110 毫秒压到 0.293 毫秒；SetPixel 每点 581 纳秒而直接写位图内存 1.5 纳秒（398 倍）；StretchBlt 缩小 8 倍时 HALFTONE 比 COLORONCOLOR 慢 207 倍；一次提前的 ReleaseDC 让后面所有 GetDeviceCaps 静默返回 0，而 GetLastError 一动不动。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>Win32</category><category>GDI</category><category>双缓冲</category><category>BitBlt</category><category>AlphaBlend</category><category>分层窗口</category></item><item><title>句柄、消息与窗口过程</title><link>https://wty.blogs.abrdns.com/posts/win-handle-message/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/win-handle-message/</guid><description>实测：句柄值是 4 字节步进的表索引，关掉再建立刻复用；一个线程的消息队列只能堆 10000 条（第 10001 次 PostMessage 报 1816 配额不足）；同线程 SendMessage 56 纳秒，跨线程 27.8 微秒，差 493 倍；USER 与 GDI 各自的配额都是每进程 10000，而 GDI 耗尽时 GetLastError 一动不动。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>Win32</category><category>句柄</category><category>消息队列</category><category>WndProc</category><category>Unicode</category></item><item><title>资源脚本与图标</title><link>https://wty.blogs.abrdns.com/posts/win-resource/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/win-resource/</guid><description>实测：同一个 .rc 只加一行 `#pragma code_page(65001)`，中文串从 9 个乱码码点变成 6 个正确码点、资源块从 70 字节缩到 64 字节；图标请求 24×24 拿到的是 32×32 源缩放后的像素（色标差 3），只有精确命中的尺寸色差为 0；RT_BITMAP 里存的是 .bmp 去掉 14 字节文件头（242→228、130→116）；4MB 自定义资源 LockResource 只花 0.9 微秒且一字节不拷，逐页采样 1024 次才让 WorkingSet 涨 4.0MB；ddores.dll 文件只有 71 600 字节，而 1096 条 RT_ICON 的 SizeofResource 合计 16 303 340 字节——228 倍，且这些数据不在文件里。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>Win32</category><category>资源</category><category>windres</category><category>图标</category><category>字符串表</category><category>本地化</category></item><item><title>线程与同步</title><link>https://wty.blogs.abrdns.com/posts/win-thread-sync/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/win-thread-sync/</guid><description>实测：CreateThread 单价 22.1 微秒、每个线程恰好 1 个内核句柄、栈一上来就提交 1040KB（再碰 700KB 一点都不加，而请求 8MB 时 8192KB 全提交）；无竞争 Enter+Leave 临界区 13.9 纳秒、互斥体 301.5 纳秒（21 倍），两线程交接时临界区 0.12 微秒、互斥体 4.68 微秒（39 倍）；UI 线程用 WaitForSingleObject 等事件时，跨线程 SendMessage 被挂 2805 毫秒，换成 MsgWaitForMultipleObjects 只阻塞 0.4 毫秒；MinGW-w64 的 GCC 13.1.0 对 `__declspec(thread)` 报 &quot;&apos;thread&apos; attribute directive ignored&quot; 并静默退化成普通静态变量——两个线程读到同一个地址。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><category>Win32</category><category>线程</category><category>临界区</category><category>SRWLOCK</category><category>WaitForMultipleObjects</category><category>TLS</category></item><item><title>开篇：为什么还要自己写一个博客</title><link>https://wty.blogs.abrdns.com/posts/hello-github-pages/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/hello-github-pages/</guid><description>在公众号、小红书、各种信息流之外，一个自己拥有域名的静态站点仍然值得拥有。</description><pubDate>Wed, 14 Oct 2026 00:00:00 GMT</pubDate><category>博客</category><category>建站</category></item><item><title>Astro 内容集合的正确用法</title><link>https://wty.blogs.abrdns.com/posts/astro-content-collections/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/astro-content-collections/</guid><description>用 glob loader 加 zod schema 把 Markdown 变成有类型约束的数据源，写错字段构建期就报错。</description><pubDate>Thu, 08 Oct 2026 00:00:00 GMT</pubDate><category>Astro</category><category>前端</category><category>建站</category></item><item><title>我每天真的只用这几条 Git 命令</title><link>https://wty.blogs.abrdns.com/posts/git-daily-workflow/</link><guid isPermaLink="true">https://wty.blogs.abrdns.com/posts/git-daily-workflow/</guid><description>抛开那些面试才用的招数，日常工作里 90% 的操作就五条命令，外加两个必须记住的救命招。</description><pubDate>Sat, 26 Sep 2026 00:00:00 GMT</pubDate><category>Git</category><category>工程实践</category></item></channel></rss>