<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>帷幕之後的虛幻城市：筆記</title>
        <link>https://blog.mukyu.tw</link>
        <description>後端工程師香草的個人網站：技術筆記、旅行照片、年度回顧與生活切片。</description>
        <lastBuildDate>Wed, 28 Oct 2026 16:18:01 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (c) 2026, 帷幕之後的虛幻城市</copyright>
        <item>
            <title><![CDATA[Nginx Load Balancer with Docker Compose]]></title>
            <link>https://blog.mukyu.tw/notes/Devops/Nginx%20Load%20Balancer%20with%20Docker%20Compose</link>
            <guid>https://blog.mukyu.tw/notes/Devops/Nginx%20Load%20Balancer%20with%20Docker%20Compose</guid>
            <pubDate>Wed, 28 Oct 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[本機快速架一個 Nginx load balancer + 多個 backend，用來測試分流。
```
lb/nginx.conf
server/Dockerfile
docker-compose.]]></description>
            <content:encoded><![CDATA[<h1 id="nginx-load-balancer-with-docker-compose" tabindex="-1">Nginx Load Balancer with Docker Compose <a class="header-anchor" href="#nginx-load-balancer-with-docker-compose" aria-label="Permalink to &quot;Nginx Load Balancer with Docker Compose&quot;"></a></h1>
<p>本機快速架一個 Nginx load balancer + 多個 backend，用來測試分流。</p>
<div class="language- vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>lb/nginx.conf</span></span>
<span class="line"><span>server/Dockerfile</span></span>
<span class="line"><span>docker-compose.yml</span></span></code></pre>
</div><h2 id="backend" tabindex="-1">Backend <a class="header-anchor" href="#backend" aria-label="Permalink to &quot;Backend&quot;"></a></h2>
<div class="language-dockerfile vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">dockerfile</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">FROM</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> python:3.12</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">CMD</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"python3"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"-m"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"http.server"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"8080"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">EXPOSE</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> 8080</span></span></code></pre>
</div><h2 id="nginx" tabindex="-1">Nginx <a class="header-anchor" href="#nginx" aria-label="Permalink to &quot;Nginx&quot;"></a></h2>
<div class="language-nginx vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">nginx</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">events</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">http</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    upstream</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> backend </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        server</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> server1:8080;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        server</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> server2:8080;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        server</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> server3:8080;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    server</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        listen </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">80</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        location</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> / </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            proxy_pass </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">http://backend;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div><ul>
<li><code>upstream</code> 預設 round-robin；可加 <code>least_conn</code>、<code>ip_hash</code> 或 <code>weight=</code></li>
<li>compose 內用 service 名稱當 hostname</li>
</ul>
<h2 id="docker-compose-yml" tabindex="-1">docker-compose.yml <a class="header-anchor" href="#docker-compose-yml" aria-label="Permalink to &quot;docker-compose.yml&quot;"></a></h2>
<div class="language-yaml vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">yaml</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">services</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  lb</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    image</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">nginx</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    volumes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      - </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">./lb/nginx.conf:/etc/nginx/nginx.conf:ro</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    ports</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      - </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">8080:80</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    depends_on</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">server1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">server2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">server3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  server1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    build</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">server/</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  server2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    build</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">server/</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">  server3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:</span></span>
<span class="line"><span style="--shiki-light:#22863A;--shiki-dark:#85E89D">    build</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">server/</span></span></code></pre>
</div><p>測試分流時 client / server 都用 async，並在 backend 記 log 再統計。</p>
<h2 id="參考" tabindex="-1">參考 <a class="header-anchor" href="#參考" aria-label="Permalink to &quot;參考&quot;"></a></h2>
<ul>
<li>原文：<a href="/blog/2020/08-21-docker-compose-nginx-load-balancer/">Docker-compose + Nginx as Load Balancer</a></li>
<li><a href="/notes/📫 Inbox/Docker.html">Docker network 模型</a></li>
</ul>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[打包 Go Binary 成 Debian Package]]></title>
            <link>https://blog.mukyu.tw/notes/Devops/%E6%89%93%E5%8C%85%20Go%20Binary%20%E6%88%90%20Debian%20Package</link>
            <guid>https://blog.mukyu.tw/notes/Devops/%E6%89%93%E5%8C%85%20Go%20Binary%20%E6%88%90%20Debian%20Package</guid>
            <pubDate>Wed, 28 Oct 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[# 打包 Go Binary 成 Debian Package

需求：把不在 apt repo 的 Go 工具穩定地打包成 `.deb`（例如裝到 `/opt/<org>/<tool>/bin`）。

## 選項

| 方式 | 優點 | 缺點 |
| ]]></description>
            <content:encoded><![CDATA[<h1 id="打包-go-binary-成-debian-package" tabindex="-1">打包 Go Binary 成 Debian Package <a class="header-anchor" href="#打包-go-binary-成-debian-package" aria-label="Permalink to &quot;打包 Go Binary 成 Debian Package&quot;"></a></h1>
<p>需求：把不在 apt repo 的 Go 工具穩定地打包成 <code>.deb</code>（例如裝到 <code>/opt/&lt;org&gt;/&lt;tool&gt;/bin</code>）。</p>
<h2 id="選項" tabindex="-1">選項 <a class="header-anchor" href="#選項" aria-label="Permalink to &quot;選項&quot;"></a></h2>
<table tabindex="0">
<thead>
<tr>
<th>方式</th>
<th>優點</th>
<th>缺點</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Script + Git Server</strong>（推薦）</td>
<td>repo 不放 binary / 外部 code；多個 Go repo 時好維護</td>
<td>要有可信任的 Git server（自架或 GitHub / GitLab）</td>
</tr>
<tr>
<td>Source code zip</td>
<td>簡單</td>
<td><code>go.mod</code> 的依賴仍要從網路抓，只解決一半</td>
</tr>
<tr>
<td>Source + <code>go mod vendor</code> zip</td>
<td>完全離線</td>
<td>vendor 的定位偏向 code review，不是保存依賴；流程和原始碼有落差，容易變技術債</td>
</tr>
</tbody>
</table>
<p>C/C++ 這類來源不穩、需要後處理（submodule）的套件，才比較適合 zip + CMake 的做法。</p>
<p>需要離線 / 防止依賴消失時，也可以考慮 Go module proxy（例如 Athens）當 read-through cache。</p>
<h2 id="參考" tabindex="-1">參考 <a class="header-anchor" href="#參考" aria-label="Permalink to &quot;參考&quot;"></a></h2>
<ul>
<li>原文：<a href="/blog/2022/08-15-go-binary-debian-package/">穩定打包 Go Binary 成 Debian Package 的選擇</a></li>
<li><a href="https://go-team.pages.debian.net/packaging.html" target="_blank" rel="noreferrer">Debian Go Packaging</a></li>
</ul>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Diff and Patch]]></title>
            <link>https://blog.mukyu.tw/notes/%F0%9F%90%A7%20Linux/Diff%20and%20Patch</link>
            <guid>https://blog.mukyu.tw/notes/%F0%9F%90%A7%20Linux/Diff%20and%20Patch</guid>
            <pubDate>Wed, 28 Oct 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[產生 patch
```bash
diff -Naur old new 
```
- `-N`：不存在的檔案視為空檔，patch 才能新增 / 刪除檔案
- `-a`：binary 也當文字比
- `]]></description>
            <content:encoded><![CDATA[<h1 id="diff-and-patch" tabindex="-1">Diff and Patch <a class="header-anchor" href="#diff-and-patch" aria-label="Permalink to &quot;Diff and Patch&quot;"></a></h1>
<h2 id="產生-patch" tabindex="-1">產生 patch <a class="header-anchor" href="#產生-patch" aria-label="Permalink to &quot;產生 patch&quot;"></a></h2>
<div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">diff</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -Naur</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> old</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> new</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> ></span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> patch.diff</span></span></code></pre>
</div><ul>
<li><code>-N</code>：不存在的檔案視為空檔，patch 才能新增 / 刪除檔案</li>
<li><code>-a</code>：binary 也當文字比</li>
<li><code>-u</code>：unified format，<strong>沒有的話 <code>patch</code> 無法解析</strong></li>
<li><code>-r</code>：遞迴資料夾</li>
</ul>
<h2 id="套用-還原" tabindex="-1">套用 / 還原 <a class="header-anchor" href="#套用-還原" aria-label="Permalink to &quot;套用 / 還原&quot;"></a></h2>
<div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">patch</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -p0</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> &#x3C;</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> patch.diff</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">      # old → new</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">patch</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -p0</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -R</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> &#x3C;</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> patch.diff</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">   # new → old</span></span></code></pre>
</div><p><code>-pN</code>：去掉 patch 內路徑前 N 層。</p>
<h2 id="參考" tabindex="-1">參考 <a class="header-anchor" href="#參考" aria-label="Permalink to &quot;參考&quot;"></a></h2>
<ul>
<li>原文：<a href="/blog/2021/11-18-linux-diff-patch/">Linux command: Diff/Patch</a></li>
<li><a href="https://man7.org/linux/man-pages/man1/diff.1.html" target="_blank" rel="noreferrer">diff(1)</a>、<a href="https://man7.org/linux/man-pages/man1/patch.1.html" target="_blank" rel="noreferrer">patch(1)</a></li>
</ul>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[OOM Killer]]></title>
            <link>https://blog.mukyu.tw/notes/%F0%9F%90%A7%20Linux/OOM%20Killer</link>
            <guid>https://blog.mukyu.tw/notes/%F0%9F%90%A7%20Linux/OOM%20Killer</guid>
            <pubDate>Wed, 28 Oct 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[記憶體不足時，kernel 用 `oom_badness()`（mm/oom_kill.c）替每個 process 打分數，分數最高的被 kill。
 不列入候選
- kthread 等 unkill]]></description>
            <content:encoded><![CDATA[<h1 id="oom-killer" tabindex="-1">OOM Killer <a class="header-anchor" href="#oom-killer" aria-label="Permalink to &quot;OOM Killer&quot;"></a></h1>
<p>記憶體不足時，kernel 用 <code>oom_badness()</code>（<a href="https://elixir.bootlin.com/linux/v6.6/source/mm/oom_kill.c#L192" target="_blank" rel="noreferrer">mm/oom_kill.c</a>）替每個 process 打分數，分數最高的被 kill。</p>
<h2 id="不列入候選" tabindex="-1">不列入候選 <a class="header-anchor" href="#不列入候選" aria-label="Permalink to &quot;不列入候選&quot;"></a></h2>
<ul>
<li>kthread 等 unkillable task</li>
<li>正在 <code>vfork</code></li>
<li><code>oom_score_adj</code> 為 <code>OOM_SCORE_ADJ_MIN</code>（-1000）</li>
<li>已被 OOM reap / 標記 <code>MMF_OOM_SKIP</code></li>
</ul>
<h2 id="分數" tabindex="-1">分數 <a class="header-anchor" href="#分數" aria-label="Permalink to &quot;分數&quot;"></a></h2>
<div class="language-c vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">c</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">points </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> rss </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> swap </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> pagetable_bytes </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> PAGE_SIZE;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">points </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> oom_score_adj </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> totalpages </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span></code></pre>
</div><ul>
<li>基準是 process 佔用的記憶體（RSS、swap、page table）</li>
<li><code>oom_score_adj</code>（-1000 ~ 1000）可手動調整：<code>/proc/&lt;pid&gt;/oom_score_adj</code></li>
<li>目前分數：<code>/proc/&lt;pid&gt;/oom_score</code></li>
</ul>
<h2 id="參考" tabindex="-1">參考 <a class="header-anchor" href="#參考" aria-label="Permalink to &quot;參考&quot;"></a></h2>
<ul>
<li>原文：<a href="/blog/2024/01-01-oom-killer/">OOM Killer 簡短筆記</a></li>
<li><a href="https://unix.stackexchange.com/questions/153585/how-does-the-oom-killer-decide-which-process-to-kill-first" target="_blank" rel="noreferrer">How does the OOM killer decide which process to kill first?</a></li>
<li><a href="https://lwn.net/SubscriberLink/941614/f873a0ec485e01c5/" target="_blank" rel="noreferrer">Out-of-memory victim selection with BPF</a></li>
</ul>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[fcntl File Lock]]></title>
            <link>https://blog.mukyu.tw/notes/%F0%9F%90%A7%20Linux/fcntl%20File%20Lock</link>
            <guid>https://blog.mukyu.tw/notes/%F0%9F%90%A7%20Linux/fcntl%20File%20Lock</guid>
            <pubDate>Wed, 28 Oct 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[`fcntl` 提供跨 process 的 read/write file lock，但 lock 屬於 process，不屬於 thread 或 fd。
 坑：同一 process 不能跨 thre]]></description>
            <content:encoded><![CDATA[<h1 id="fcntl-file-lock" tabindex="-1">fcntl File Lock <a class="header-anchor" href="#fcntl-file-lock" aria-label="Permalink to &quot;fcntl File Lock&quot;"></a></h1>
<p><code>fcntl</code> 提供跨 process 的 read/write file lock，但 <strong>lock 屬於 process，不屬於 thread 或 fd</strong>。</p>
<h2 id="坑-同一-process-不能跨-thread-共用" tabindex="-1">坑：同一 process 不能跨 thread 共用 <a class="header-anchor" href="#坑-同一-process-不能跨-thread-共用" aria-label="Permalink to &quot;坑：同一 process 不能跨 thread 共用&quot;"></a></h2>
<blockquote>
<p>If a process closes any file descriptor referring to a file, then all of the process's locks on that file are released, regardless of the file descriptor(s) on which the locks were obtained.</p>
</blockquote>
<ul>
<li>Thread 1、Thread 2 都對 <code>mydata.lock</code> 上 read lock</li>
<li>其中一個 unlock 或 close fd → <strong>整個 process</strong> 失去這把 lock</li>
<li>另一個 thread 以為自己還持有，實際上已經沒有保護</li>
</ul>
<h2 id="解法" tabindex="-1">解法 <a class="header-anchor" href="#解法" aria-label="Permalink to &quot;解法&quot;"></a></h2>
<ul>
<li>每個 thread 用不同的 lock 檔（拆成多把 lock）</li>
<li>或在 process 內另外用 mutex / 計數管理，只由一個地方持有 fcntl lock</li>
<li>Linux 3.15+ 可考慮 OFD lock（<code>F_OFD_SETLK</code>），lock 綁在 open file description 上</li>
</ul>
<h2 id="參考" tabindex="-1">參考 <a class="header-anchor" href="#參考" aria-label="Permalink to &quot;參考&quot;"></a></h2>
<ul>
<li>原文：<a href="/blog/2023/04-10-linux-fcntl-filelock-process-thread/">Linux fcntl Filelock 中的小坑：在同一 Process 不能跨 Thread 使用</a></li>
<li><a href="https://man7.org/linux/man-pages/man2/fcntl.2.html" target="_blank" rel="noreferrer">fcntl(2)</a></li>
</ul>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[pthread Cancel and Signal]]></title>
            <link>https://blog.mukyu.tw/notes/%F0%9F%90%A7%20Linux/pthread%20Cancel%20and%20Signal</link>
            <guid>https://blog.mukyu.tw/notes/%F0%9F%90%A7%20Linux/pthread%20Cancel%20and%20Signal</guid>
            <pubDate>Wed, 28 Oct 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Thread 也是 process
Linux 排程時每個 thread 都有自己的 tid（`gettid()`），`kill -s SIG &lt;tid
 `pthread_kill`
- 在 ]]></description>
            <content:encoded><![CDATA[<h1 id="pthread-cancel-and-signal" tabindex="-1">pthread Cancel and Signal <a class="header-anchor" href="#pthread-cancel-and-signal" aria-label="Permalink to &quot;pthread Cancel and Signal&quot;"></a></h1>
<h2 id="thread-也是-process" tabindex="-1">Thread 也是 process <a class="header-anchor" href="#thread-也是-process" aria-label="Permalink to &quot;Thread 也是 process&quot;"></a></h2>
<p>Linux 排程時每個 thread 都有自己的 tid（<code>gettid()</code>），<code>kill -s SIG &lt;tid&gt;</code> 會讓<strong>該 thread</strong> 執行 signal handler。</p>
<h2 id="pthread-kill" tabindex="-1"><code>pthread_kill</code> <a class="header-anchor" href="#pthread-kill" aria-label="Permalink to &quot;`pthread_kill`&quot;"></a></h2>
<ul>
<li>在 process 內對指定 thread 送 signal</li>
<li>被 signal 打斷的 <code>sleep</code> 等 blocking call 會提早返回</li>
</ul>
<h2 id="pthread-cancel" tabindex="-1"><code>pthread_cancel</code> <a class="header-anchor" href="#pthread-cancel" aria-label="Permalink to &quot;`pthread_cancel`&quot;"></a></h2>
<ul>
<li>只在 cancellation point（大多是 IO、<code>sleep</code> 等 blocking call）中斷 thread</li>
<li>glibc 實作：對目標 thread 送 signal → handler 呼叫 <code>__do_cancel</code> → <code>__pthread_unwind</code> → <code>_Unwind_ForcedUnwind</code></li>
<li>因為是 forced unwind，<strong>glibc 下 C++ destructor 會被呼叫</strong>；macOS（Apple clang）實測不會</li>
<li>行為不在標準內，跨平台不要依賴，一般也不建議用 <code>pthread_cancel</code></li>
</ul>
<h2 id="參考" tabindex="-1">參考 <a class="header-anchor" href="#參考" aria-label="Permalink to &quot;參考&quot;"></a></h2>
<ul>
<li>原文：<a href="/blog/2023/11-23-pthread-cancel-and-destructor/">pthread_cancel 與解構子行為實驗</a>、<a href="/blog/2023/11-24-pthread-kill-exp/">pthread_kill 實驗</a></li>
<li><a href="https://man7.org/linux/man-pages/man3/pthread_cancel.3.html" target="_blank" rel="noreferrer">pthread_cancel(3)</a>、<a href="https://man7.org/linux/man-pages/man3/pthread_kill.3.html" target="_blank" rel="noreferrer">pthread_kill(3)</a></li>
<li><a href="https://skaark.wordpress.com/2010/08/26/pthread_cancel-considered-harmful/" target="_blank" rel="noreferrer">pthread_cancel considered harmful</a></li>
</ul>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[多使用者共用檔案]]></title>
            <link>https://blog.mukyu.tw/notes/%F0%9F%90%A7%20Linux/%E5%A4%9A%E4%BD%BF%E7%94%A8%E8%80%85%E5%85%B1%E7%94%A8%E6%AA%94%E6%A1%88</link>
            <guid>https://blog.mukyu.tw/notes/%F0%9F%90%A7%20Linux/%E5%A4%9A%E4%BD%BF%E7%94%A8%E8%80%85%E5%85%B1%E7%94%A8%E6%AA%94%E6%A1%88</guid>
            <pubDate>Wed, 28 Oct 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[新檔案拿不到 group write
`open(path, O_CREAT, 0664)` 實際權限是 `mode & ~umask`，預設 umask `022` 會關掉 group write。]]></description>
            <content:encoded><![CDATA[<h1 id="多使用者共用檔案" tabindex="-1">多使用者共用檔案 <a class="header-anchor" href="#多使用者共用檔案" aria-label="Permalink to &quot;多使用者共用檔案&quot;"></a></h1>
<h2 id="新檔案拿不到-group-write" tabindex="-1">新檔案拿不到 group write <a class="header-anchor" href="#新檔案拿不到-group-write" aria-label="Permalink to &quot;新檔案拿不到 group write&quot;"></a></h2>
<p><code>open(path, O_CREAT, 0664)</code> 實際權限是 <code>mode &amp; ~umask</code>，預設 umask <code>022</code> 會關掉 group write。</p>
<p>解法：</p>
<ul>
<li>
<p><strong>Default ACL（推薦）</strong>：對資料夾設定，之後新建的檔案都會繼承</p>
<div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">setfacl</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -d</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -m</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> g:myteam:rwx</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> &#x3C;</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">di</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">r</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">></span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">getfacl</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> &#x3C;</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">di</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">r</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">></span></span></code></pre>
</div></li>
<li>
<p><code>umask(002)</code>：process 層級，不是 thread-safe，暫時改再改回去會有 race</p>
</li>
<li>
<p>建立後再 <code>chmod</code>：中間有時間差</p>
</li>
</ul>
<h2 id="git-unsafe-repository" tabindex="-1">Git：<code>unsafe repository</code> <a class="header-anchor" href="#git-unsafe-repository" aria-label="Permalink to &quot;Git：`unsafe repository`&quot;"></a></h2>
<p>Git 2.35.2 起（<a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-24765" target="_blank" rel="noreferrer">CVE-2022-24765</a>），repo owner 不是目前使用者時，連 <code>git log</code> 都會拒絕：</p>
<div class="language- vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span>fatal: unsafe repository ('/path/to/repo' is owned by someone else)</span></span></code></pre>
</div><p>信任該路徑：</p>
<div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> config</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --global</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> --add</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> safe.directory</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> /path/to/repo</span></span></code></pre>
</div><p>沒有 group 層級的設定。</p>
<h2 id="參考" tabindex="-1">參考 <a class="header-anchor" href="#參考" aria-label="Permalink to &quot;參考&quot;"></a></h2>
<ul>
<li>原文：<a href="/blog/2022/03-25-group-write-permission-pitfall/">一個 Group Write Permission 的坑</a>、<a href="/blog/2022/05-06-git-repository-access-control/">Git Repository 限制使用者存取</a></li>
<li><a href="https://git-scm.com/docs/git-config/#Documentation/git-config.txt-safedirectory" target="_blank" rel="noreferrer">git-config: safe.directory</a></li>
</ul>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Copy, Move 與 RAII]]></title>
            <link>https://blog.mukyu.tw/notes/%F0%9F%A7%B1%20C++/Copy%20Move%20%E8%88%87%20RAII</link>
            <guid>https://blog.mukyu.tw/notes/%F0%9F%A7%B1%20C++/Copy%20Move%20%E8%88%87%20RAII</guid>
            <pubDate>Wed, 28 Oct 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[# Copy, Move 與 RAII

C++ 用 destructor 自動釋放資源（RAII），但 class 持有 raw pointer 時，只寫 constructor / destructor 不夠。

## Rule of Five

| 函數 | 簽名 |
| ]]></description>
            <content:encoded><![CDATA[<h1 id="copy-move-與-raii" tabindex="-1">Copy, Move 與 RAII <a class="header-anchor" href="#copy-move-與-raii" aria-label="Permalink to &quot;Copy, Move 與 RAII&quot;"></a></h1>
<p>C++ 用 destructor 自動釋放資源（RAII），但 class 持有 raw pointer 時，只寫 constructor / destructor 不夠。</p>
<h2 id="rule-of-five" tabindex="-1">Rule of Five <a class="header-anchor" href="#rule-of-five" aria-label="Permalink to &quot;Rule of Five&quot;"></a></h2>
<table tabindex="0">
<thead>
<tr>
<th>函數</th>
<th>簽名</th>
</tr>
</thead>
<tbody>
<tr>
<td>copy constructor</td>
<td><code>C(const C&amp;)</code></td>
</tr>
<tr>
<td>copy assignment</td>
<td><code>C&amp; operator=(const C&amp;)</code></td>
</tr>
<tr>
<td>move constructor</td>
<td><code>C(C&amp;&amp;)</code></td>
</tr>
<tr>
<td>move assignment</td>
<td><code>C&amp; operator=(C&amp;&amp;)</code></td>
</tr>
<tr>
<td>destructor</td>
<td><code>~C()</code></td>
</tr>
</tbody>
</table>
<p>編譯器自動生成的 copy 只複製指標 → 兩個物件指向同一塊記憶體 → double free。</p>
<h2 id="copy-copy-and-swap" tabindex="-1">Copy：copy-and-swap <a class="header-anchor" href="#copy-copy-and-swap" aria-label="Permalink to &quot;Copy：copy-and-swap&quot;"></a></h2>
<div class="language-cpp vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">cpp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">IntBuff</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> operator</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> IntBuff</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> ib</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    IntBuff </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">tmp</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(ib);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">          // 可能 throw 的部分先做</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    std</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">::</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">swap</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(arr, tmp.arr);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  // 不會 throw 才改自己</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    std</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">::</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">swap</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(sz, tmp.sz);</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> *</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div><p>順便處理了 self-assignment 與 <a href="./Exception Safety.html">exception safety</a>。</p>
<h2 id="move" tabindex="-1">Move <a class="header-anchor" href="#move" aria-label="Permalink to &quot;Move&quot;"></a></h2>
<ul>
<li>r-value：只能放在等號右邊的值，例如 <code>foo()</code>、<code>b + 1</code>、<code>99</code></li>
<li><code>T&amp;&amp;</code> 綁定 r-value；<code>std::move(x)</code> 把 l-value 轉成 r-value reference</li>
<li>實作 move：接手指標，並把來源設成「空」，避免重複釋放</li>
</ul>
<div class="language-cpp vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">cpp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">IntBuff</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(IntBuff</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;&#x26;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> ib) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">noexcept</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">arr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(ib.arr), </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">sz</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(ib.sz) {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    ib.arr </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> nullptr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    ib.sz </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div><h2 id="std-unique-ptr" tabindex="-1"><code>std::unique_ptr</code> <a class="header-anchor" href="#std-unique-ptr" aria-label="Permalink to &quot;`std::unique_ptr`&quot;"></a></h2>
<p>一個 class 管理一個資源。成員改成 <code>std::unique_ptr&lt;int[]&gt;</code> 後：</p>
<ul>
<li>不用手寫 <code>delete</code></li>
<li>move 直接 <code>= default</code></li>
<li>copy 被禁止，需要時自己實作（new 一份再複製內容）</li>
</ul>
<div class="language-cpp vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">cpp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> IntBuff</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public:</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    explicit</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> IntBuff</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">size_t</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> sz</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">arr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">std</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">::</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">make_unique</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[]>(sz)), </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">sz</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(sz) {}</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    IntBuff</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> IntBuff</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> ib</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">IntBuff</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(ib.sz) {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        std</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">::</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">copy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(ib.arr.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(), ib.arr.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> sz, arr.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">());</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    IntBuff</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> operator</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> IntBuff</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> ib</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        IntBuff </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">tmp</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(ib);</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">        std</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">::</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">swap</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, tmp);</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> *</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    IntBuff</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">IntBuff</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;&#x26;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">noexcept</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    IntBuff</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> operator</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">IntBuff</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;&#x26;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">noexcept</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">private:</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    std</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">::unique_ptr</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[]</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> arr;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    size_t</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> sz </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">};</span></span></code></pre>
</div><h2 id="參考" tabindex="-1">參考 <a class="header-anchor" href="#參考" aria-label="Permalink to &quot;參考&quot;"></a></h2>
<ul>
<li>原文：<a href="/blog/2020/03-15-way-to-cpp-1-copy-constructor/">1. Copy Constructor</a>、<a href="/blog/2020/03-18-way-to-cpp-2-move/">2. Move</a>、<a href="/blog/2020/03-19-way-to-cpp-3-std-unique-ptr/">3. std::unique_ptr</a></li>
</ul>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Defer 與自訂 Deleter]]></title>
            <link>https://blog.mukyu.tw/notes/%F0%9F%A7%B1%20C++/Defer%20%E8%88%87%E8%87%AA%E8%A8%82%20Deleter</link>
            <guid>https://blog.mukyu.tw/notes/%F0%9F%A7%B1%20C++/Defer%20%E8%88%87%E8%87%AA%E8%A8%82%20Deleter</guid>
            <pubDate>Wed, 28 Oct 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[目標：離開 scope 時自動 `fclose`。
 `std::unique_ptr` + deleter
```cpp
std::unique_ptr&lt;FILE, decltype(&fcl]]></description>
            <content:encoded><![CDATA[<h1 id="defer-與自訂-deleter" tabindex="-1">Defer 與自訂 Deleter <a class="header-anchor" href="#defer-與自訂-deleter" aria-label="Permalink to &quot;Defer 與自訂 Deleter&quot;"></a></h1>
<p>目標：離開 scope 時自動 <code>fclose</code>。</p>
<h2 id="std-unique-ptr-deleter" tabindex="-1"><code>std::unique_ptr</code> + deleter <a class="header-anchor" href="#std-unique-ptr-deleter" aria-label="Permalink to &quot;`std::unique_ptr` + deleter&quot;"></a></h2>
<div class="language-cpp vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">cpp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">std</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">::</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">unique_ptr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">FILE</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">decltype</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">fclose)> </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">fp</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">fopen</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(path, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"r"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">), </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">fclose</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">!</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">fp) {</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"> /* 開檔失敗 */</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> }</span></span></code></pre>
</div><ul>
<li>型別是 <code>FILE</code> 不是 <code>FILE*</code></li>
<li><code>unique_ptr</code> 為空時不會呼叫 deleter，<code>fopen</code> 失敗也安全</li>
</ul>
<h2 id="自製-defer" tabindex="-1">自製 Defer <a class="header-anchor" href="#自製-defer" aria-label="Permalink to &quot;自製 Defer&quot;"></a></h2>
<div class="language-cpp vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">cpp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">struct</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Defer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    template</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> &#x3C;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">typename</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> F</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    explicit</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Defer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">F</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;&#x26;</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">func_</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">std</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">::</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">forward</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">F</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>(f)) {}</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    ~Defer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() { </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">func_</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(); }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Defer</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Defer</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> delete</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Defer</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> operator</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Defer</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> delete</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">private:</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    std</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">::function</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;void</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> func_;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Defer</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> d</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">([</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">] { </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">fclose</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(fp); });</span></span></code></pre>
</div><p><code>std::function</code> 可以吃 lambda、<code>std::bind</code>、function pointer。</p>
<h2 id="參考" tabindex="-1">參考 <a class="header-anchor" href="#參考" aria-label="Permalink to &quot;參考&quot;"></a></h2>
<ul>
<li>原文：<a href="/blog/2020/04-03-way-to-cpp-4-auto-close/">Way to C++: 4. Auto close (雜)</a></li>
</ul>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Exception Safety]]></title>
            <link>https://blog.mukyu.tw/notes/%F0%9F%A7%B1%20C++/Exception%20Safety</link>
            <guid>https://blog.mukyu.tw/notes/%F0%9F%A7%B1%20C++/Exception%20Safety</guid>
            <pubDate>Wed, 28 Oct 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[# Exception Safety

`new` 失敗會 throw，下面的 `arr1` 就 leak 了：

```cpp
int* arr1 = new int[n];
int* arr2 = new int[n];  // throw → arr1 沒被釋放
```

解法：每個資源交給一個 RAII 物件（`std::unique_ptr`、`std::vector`…），不要逐個 try-catch。

## 等級

| 等級 | 保證 |
| ]]></description>
            <content:encoded><![CDATA[<h1 id="exception-safety" tabindex="-1">Exception Safety <a class="header-anchor" href="#exception-safety" aria-label="Permalink to &quot;Exception Safety&quot;"></a></h1>
<p><code>new</code> 失敗會 throw，下面的 <code>arr1</code> 就 leak 了：</p>
<div class="language-cpp vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">cpp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">int*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> arr1 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[n];</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">int*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> arr2 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> new</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> int</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[n];</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  // throw → arr1 沒被釋放</span></span></code></pre>
</div><p>解法：每個資源交給一個 RAII 物件（<code>std::unique_ptr</code>、<code>std::vector</code>…），不要逐個 try-catch。</p>
<h2 id="等級" tabindex="-1">等級 <a class="header-anchor" href="#等級" aria-label="Permalink to &quot;等級&quot;"></a></h2>
<table tabindex="0">
<thead>
<tr>
<th>等級</th>
<th>保證</th>
</tr>
</thead>
<tbody>
<tr>
<td>Basic</td>
<td>不 leak、物件狀態仍合法</td>
</tr>
<tr>
<td>Strong</td>
<td>失敗時狀態回到操作前（rollback）</td>
</tr>
<tr>
<td>No-throw</td>
<td>不會 throw</td>
</tr>
</tbody>
</table>
<p>越強成本通常越高。</p>
<h2 id="技巧" tabindex="-1">技巧 <a class="header-anchor" href="#技巧" aria-label="Permalink to &quot;技巧&quot;"></a></h2>
<ul>
<li><strong>copy-and-swap</strong>：先做可能 throw 的 copy，再用不會 throw 的 swap 修改自己 → strong guarantee</li>
<li>move constructor / swap 盡量標 <code>noexcept</code>，<code>std::vector</code> 擴容時才會用 move 而不是 copy</li>
</ul>
<h2 id="參考" tabindex="-1">參考 <a class="header-anchor" href="#參考" aria-label="Permalink to &quot;參考&quot;"></a></h2>
<ul>
<li>原文：<a href="/blog/2020/05-10-way-to-cpp-6-exception-safe/">Way to C++: 6. Exception Safe</a>、<a href="/blog/2020/03-19-way-to-cpp-3-std-unique-ptr/">3. std::unique_ptr</a></li>
</ul>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Forwarding Reference]]></title>
            <link>https://blog.mukyu.tw/notes/%F0%9F%A7%B1%20C++/Forwarding%20Reference</link>
            <guid>https://blog.mukyu.tw/notes/%F0%9F%A7%B1%20C++/Forwarding%20Reference</guid>
            <pubDate>Wed, 28 Oct 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[想寫一個 wrapper，把參數原封不動（l-value / r-value）轉給 `foo`：
```cpp
template &lt;typename T
void callFoo(T&& val]]></description>
            <content:encoded><![CDATA[<h1 id="forwarding-reference" tabindex="-1">Forwarding Reference <a class="header-anchor" href="#forwarding-reference" aria-label="Permalink to &quot;Forwarding Reference&quot;"></a></h1>
<p>想寫一個 wrapper，把參數原封不動（l-value / r-value）轉給 <code>foo</code>：</p>
<div class="language-cpp vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">cpp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">template</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> &#x3C;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">typename</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> T</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> callFoo</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">T</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;&#x26;</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> val</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">          // forwarding reference</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    foo</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">std</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">::</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">forward</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">T</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>(val));</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">   // 保留 value category</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div><ul>
<li>只有在 <strong>template 型別推導</strong> 時，<code>T&amp;&amp;</code> 才是 forwarding reference；<code>int&amp;&amp;</code> 就只是 r-value reference</li>
<li>推導：傳 l-value → <code>T = U&amp;</code>，傳 r-value → <code>T = U</code></li>
<li>有名字的變數一律是 l-value，所以直接 <code>foo(val)</code> 永遠呼叫 l-value 版本，需要 <code>std::forward&lt;T&gt;</code></li>
</ul>
<h2 id="參考" tabindex="-1">參考 <a class="header-anchor" href="#參考" aria-label="Permalink to &quot;參考&quot;"></a></h2>
<ul>
<li>原文：<a href="/blog/2020/04-22-way-to-cpp-5-forwarding-reference/">Way to C++: 5. Forwarding Reference</a></li>
</ul>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Memory Alignment]]></title>
            <link>https://blog.mukyu.tw/notes/%F0%9F%A7%B1%20C++/Memory%20Alignment</link>
            <guid>https://blog.mukyu.tw/notes/%F0%9F%A7%B1%20C++/Memory%20Alignment</guid>
            <pubDate>Wed, 28 Oct 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[CPU 以 word 為單位讀取，變數的起始位置通常是自身大小的倍數，否則可能要讀兩個 word。
 Struct 規則
- alignment = 最寬成員的 alignment
- 成員之間補 p]]></description>
            <content:encoded><![CDATA[<h1 id="memory-alignment" tabindex="-1">Memory Alignment <a class="header-anchor" href="#memory-alignment" aria-label="Permalink to &quot;Memory Alignment&quot;"></a></h1>
<p>CPU 以 word 為單位讀取，變數的起始位置通常是自身大小的倍數，否則可能要讀兩個 word。</p>
<h2 id="struct-規則" tabindex="-1">Struct 規則 <a class="header-anchor" href="#struct-規則" aria-label="Permalink to &quot;Struct 規則&quot;"></a></h2>
<ul>
<li>alignment = 最寬成員的 alignment</li>
<li>成員之間補 padding 以滿足各自的 alignment</li>
<li>尾端補 padding，讓 <code>sizeof</code> 是 alignment 的倍數（當作陣列時仍對齊）</li>
<li>padding 的內容不保證是 0</li>
</ul>
<div class="language-c vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">c</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">struct</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> bar {</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">       // sizeof = 24</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    char</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> c;</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // 1 + 7 padding</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    uint64_t</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> v1;</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">   // 8</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    uint16_t</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> v2;</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">   // 2 + 6 padding</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">struct</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> bar2 {</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">      // sizeof = 16</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    uint64_t</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> v1;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    uint16_t</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> v2;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    char</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> c;</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        // 尾端 5 padding</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">};</span></span></code></pre>
</div><h2 id="減少-padding" tabindex="-1">減少 padding <a class="header-anchor" href="#減少-padding" aria-label="Permalink to &quot;減少 padding&quot;"></a></h2>
<ul>
<li><strong>由大到小排列成員</strong>；代價是可讀性，以及相關欄位分開可能影響 cache</li>
<li><code>__attribute__((packed))</code>：完全不補 padding，存取可能變慢或在某些架構上出錯</li>
</ul>
<h2 id="檢查" tabindex="-1">檢查 <a class="header-anchor" href="#檢查" aria-label="Permalink to &quot;檢查&quot;"></a></h2>
<ul>
<li><code>sizeof(T)</code>、<code>offsetof(T, member)</code>、<code>alignof(T)</code></li>
<li>Go 不支援 packed struct，cgo 需注意（<a href="https://github.com/golang/go/wiki/cgo#struct-alignment-issues" target="_blank" rel="noreferrer">cgo wiki</a>）</li>
</ul>
<h2 id="參考" tabindex="-1">參考 <a class="header-anchor" href="#參考" aria-label="Permalink to &quot;參考&quot;"></a></h2>
<ul>
<li>原文：<a href="/blog/2020/07-02-c-cpp-memory-alignment/">C/C++ Memory Alignment</a></li>
<li><a href="http://www.catb.org/esr/structure-packing/" target="_blank" rel="noreferrer">The Lost Art of Structure Packing</a></li>
</ul>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Type Erasure]]></title>
            <link>https://blog.mukyu.tw/notes/%F0%9F%A7%B1%20C++/Type%20Erasure</link>
            <guid>https://blog.mukyu.tw/notes/%F0%9F%A7%B1%20C++/Type%20Erasure</guid>
            <pubDate>Wed, 28 Oct 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[用「多型 + 模板」把任意型別包成同一個型別，也就是 `std::function` 的做法。
 結構
```cpp
struct CallableBase {                    ]]></description>
            <content:encoded><![CDATA[<h1 id="type-erasure" tabindex="-1">Type Erasure <a class="header-anchor" href="#type-erasure" aria-label="Permalink to &quot;Type Erasure&quot;"></a></h1>
<p>用「多型 + 模板」把任意型別包成同一個型別，也就是 <code>std::function</code> 的做法。</p>
<h2 id="結構" tabindex="-1">結構 <a class="header-anchor" href="#結構" aria-label="Permalink to &quot;結構&quot;"></a></h2>
<div class="language-cpp vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">cpp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">struct</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> CallableBase</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">                     // 1. 抽象介面</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    virtual</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> ~CallableBase</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    virtual</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> call</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    virtual</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> std</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">::</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">unique_ptr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">CallableBase</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">clone</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">template</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> &#x3C;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">typename</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> F</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">struct</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> CallableImpl</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : CallableBase {</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">      // 2. 模板實作，記住真正的型別</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    F f;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    explicit</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> CallableImpl</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">F</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">std</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">::</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">move</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(f)) {}</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> call</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">override</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> { </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(); }</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    std</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">::</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">unique_ptr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">CallableBase</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">clone</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> override</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> std</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">::</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">make_unique</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">CallableImpl</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Callable</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">                          // 3. 對外的值型別</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public:</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    template</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> &#x3C;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">typename</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> F</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">              typename </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> std</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">::</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">enable_if_t</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">!</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">std</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">::</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">is_same_v</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">std</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">::</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">decay_t</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">F</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Callable</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>>></span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Callable</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">F</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">p_</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">std</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">::</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">make_unique</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">CallableImpl</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">F</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>>(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">std</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">::</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">move</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(f))) {}</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Callable</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Callable</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> o</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) : </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">p_</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(o.p_ </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">?</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> o.p_-></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">clone</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> nullptr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {}</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Callable</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> operator</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Callable</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> o</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        Callable </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">tmp</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(o);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        p_.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">swap</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(tmp.p_);</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> *</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Callable</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Callable</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;&#x26;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Callable</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> operator</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Callable</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;&#x26;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    void</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> operator</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">()</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() { </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (p_) p_-></span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">call</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(); }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">private:</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    std</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">::unique_ptr</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">CallableBase</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> p_;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">};</span></span></code></pre>
</div><h2 id="重點" tabindex="-1">重點 <a class="header-anchor" href="#重點" aria-label="Permalink to &quot;重點&quot;"></a></h2>
<ul>
<li>比起直接 <code>template &lt;typename F&gt; void foo(F)</code>，型別錯誤會在呼叫端就報出來</li>
<li><code>unique_ptr</code> 不能 copy → 需要 virtual <code>clone()</code></li>
<li>模板 constructor 要排除 <code>Callable</code> 自己，否則 copy 非 const 物件會優先匹配模板，包成 <code>CallableImpl&lt;Callable&gt;</code> 並無限遞迴</li>
<li>進一步：支援 <code>Callable&lt;R(Args...)&gt;</code> 簽名</li>
</ul>
<h2 id="參考" tabindex="-1">參考 <a class="header-anchor" href="#參考" aria-label="Permalink to &quot;參考&quot;"></a></h2>
<ul>
<li>原文：<a href="/blog/2024/05-14-cpp-type-erase-duck-type/">簡介 C++ 的 Type Erase (用多型和模板做 Duck Type)</a></li>
</ul>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[enable_shared_from_this]]></title>
            <link>https://blog.mukyu.tw/notes/%F0%9F%A7%B1%20C++/enable_shared_from_this</link>
            <guid>https://blog.mukyu.tw/notes/%F0%9F%A7%B1%20C++/enable_shared_from_this</guid>
            <pubDate>Wed, 28 Oct 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[在 member function 裡拿到自己的 `shared_ptr` / `weak_ptr`。
 錯誤做法
`std::shared_ptr&lt;Foo
 用法
1. `public` 繼承]]></description>
            <content:encoded><![CDATA[<h1 id="enable-shared-from-this" tabindex="-1">enable_shared_from_this <a class="header-anchor" href="#enable-shared-from-this" aria-label="Permalink to &quot;enable_shared_from_this&quot;"></a></h1>
<p>在 member function 裡拿到自己的 <code>shared_ptr</code> / <code>weak_ptr</code>。</p>
<h2 id="錯誤做法" tabindex="-1">錯誤做法 <a class="header-anchor" href="#錯誤做法" aria-label="Permalink to &quot;錯誤做法&quot;"></a></h2>
<p><code>std::shared_ptr&lt;Foo&gt;(this)</code> 會建立<strong>另一組</strong> control block → 同一物件被 delete 兩次。</p>
<h2 id="用法" tabindex="-1">用法 <a class="header-anchor" href="#用法" aria-label="Permalink to &quot;用法&quot;"></a></h2>
<ol>
<li><code>public</code> 繼承 <code>std::enable_shared_from_this&lt;T&gt;</code></li>
<li>呼叫 <code>shared_from_this()</code> 或 <code>weak_from_this()</code>（C++17）</li>
</ol>
<p>原理：<code>shared_ptr</code> 建構時偵測到這個 base，就把自己存進其中的 <code>weak_ptr</code>。</p>
<h2 id="坑" tabindex="-1">坑 <a class="header-anchor" href="#坑" aria-label="Permalink to &quot;坑&quot;"></a></h2>
<p>物件不是由 <code>shared_ptr</code> 管理時，<code>shared_from_this()</code> 會 throw <code>std::bad_weak_ptr</code>。</p>
<p>→ constructor 設 <code>private</code>，只提供 factory：</p>
<div class="language-cpp vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">cpp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">class</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Node</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> : </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> std</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">::</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">enable_shared_from_this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Node</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">public:</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    static</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> std</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">::</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">shared_ptr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Node</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">create</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> std</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">::</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">shared_ptr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Node</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">>(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Node</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">());</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> setLeft</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">std</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">::</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">shared_ptr</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">&#x3C;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Node</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">> </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">node</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        left_ </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> node;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        left_->parent_ </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> weak_from_this</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">();</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  // parent 用 weak_ptr 避免循環</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">private:</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    Node</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    std</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">::weak_ptr</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Node</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> parent_;</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">    std</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">::shared_ptr</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">Node</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> left_;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">};</span></span></code></pre>
</div><h2 id="參考" tabindex="-1">參考 <a class="header-anchor" href="#參考" aria-label="Permalink to &quot;參考&quot;"></a></h2>
<ul>
<li>原文：<a href="/blog/2023/11-06-std-enable-shared-from-this/">取得自己的 shared pointer</a></li>
<li><a href="https://en.cppreference.com/w/cpp/memory/enable_shared_from_this" target="_blank" rel="noreferrer">cppreference: enable_shared_from_this</a></li>
</ul>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[errno 與 gmtime_r]]></title>
            <link>https://blog.mukyu.tw/notes/%F0%9F%A7%B1%20C++/errno%20%E8%88%87%20gmtime_r</link>
            <guid>https://blog.mukyu.tw/notes/%F0%9F%A7%B1%20C++/errno%20%E8%88%87%20gmtime_r</guid>
            <pubDate>Wed, 28 Oct 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[errno 的正確用法
- 函數不會清掉 errno
- 只有函數回報失敗時（回傳 `NULL`、`-1` 等，看文件），errno 才有意義
```c
// ❌ 成功時 errno 也可能非 0（內]]></description>
            <content:encoded><![CDATA[<h1 id="errno-與-gmtime-r" tabindex="-1">errno 與 gmtime_r <a class="header-anchor" href="#errno-與-gmtime-r" aria-label="Permalink to &quot;errno 與 gmtime_r&quot;"></a></h1>
<h2 id="errno-的正確用法" tabindex="-1">errno 的正確用法 <a class="header-anchor" href="#errno-的正確用法" aria-label="Permalink to &quot;errno 的正確用法&quot;"></a></h2>
<ul>
<li>函數<strong>不會</strong>清掉 errno</li>
<li>只有函數回報失敗時（回傳 <code>NULL</code>、<code>-1</code> 等，看文件），errno 才有意義</li>
</ul>
<div class="language-c vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">c</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// ❌ 成功時 errno 也可能非 0（內部 open 時區檔失敗但有 fallback）</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">errno </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">gmtime_r</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">t</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">tm</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (errno) </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">perror</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"gmtime_r"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// ✅</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">!</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">gmtime_r</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">t</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">tm</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)) </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">perror</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"gmtime_r"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span></code></pre>
</div><h2 id="gmtime-r-的效能" tabindex="-1">gmtime_r 的效能 <a class="header-anchor" href="#gmtime-r-的效能" aria-label="Permalink to &quot;gmtime_r 的效能&quot;"></a></h2>
<ul>
<li><code>gmtime_r</code> 與 <code>localtime_r</code> 共用實作，會呼叫 <code>tzset_internal</code> 讀時區設定並更新全域狀態</li>
<li>thread-safe 是靠 lock → 多 thread 頻繁呼叫時大量時間花在 kernel mode</li>
<li>高頻呼叫可以考慮自己算，或用 Boost Posix Time、C++20 <code>&lt;chrono&gt;</code></li>
</ul>
<h2 id="參考" tabindex="-1">參考 <a class="header-anchor" href="#參考" aria-label="Permalink to &quot;參考&quot;"></a></h2>
<ul>
<li>原文：<a href="/blog/2023/01-20-c-error-handling-errno/">C Error Handling: errno</a>、<a href="/blog/2023/01-31-gmtime-r/">gmtime_r 使用性?</a></li>
<li><a href="https://codebrowser.dev/glibc/glibc/time/gmtime.c.html" target="_blank" rel="noreferrer">gmtime source</a></li>
</ul>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[sizeof]]></title>
            <link>https://blog.mukyu.tw/notes/%F0%9F%A7%B1%20C++/sizeof</link>
            <guid>https://blog.mukyu.tw/notes/%F0%9F%A7%B1%20C++/sizeof</guid>
            <pubDate>Wed, 28 Oct 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[陣列參數會退化成指標
```cpp
void f1(char a[20]);            // 其實是 char*，sizeof(a) == 8
void f2(char (&a)[10])]]></description>
            <content:encoded><![CDATA[<h1 id="sizeof" tabindex="-1">sizeof <a class="header-anchor" href="#sizeof" aria-label="Permalink to &quot;sizeof&quot;"></a></h1>
<h2 id="陣列參數會退化成指標" tabindex="-1">陣列參數會退化成指標 <a class="header-anchor" href="#陣列參數會退化成指標" aria-label="Permalink to &quot;陣列參數會退化成指標&quot;"></a></h2>
<div class="language-cpp vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">cpp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> f1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">char</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> a</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">20</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">            // 其實是 char*，sizeof(a) == 8</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> f2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">char</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">a)[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">         // reference，sizeof(a) == 10，只收長度 10</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">template</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> &#x3C;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">size_t</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> N</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">></span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> f3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">char</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x26;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">a)[N]);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">          // reference + 推導，任意長度都正確</span></span></code></pre>
</div><p>要保留長度：用 array reference + template，或改用 <code>std::array</code> / <code>std::span</code>。</p>
<h2 id="不建構物件取得成員大小" tabindex="-1">不建構物件取得成員大小 <a class="header-anchor" href="#不建構物件取得成員大小" aria-label="Permalink to &quot;不建構物件取得成員大小&quot;"></a></h2>
<div class="language-cpp vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">cpp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">sizeof</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Foo</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">::m);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">             // C++11</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">sizeof</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(((Foo</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)->m);</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">       // C 寫法：sizeof 不會真的 evaluate</span></span></code></pre>
</div><h2 id="參考" tabindex="-1">參考 <a class="header-anchor" href="#參考" aria-label="Permalink to &quot;參考&quot;"></a></h2>
<ul>
<li>原文：<a href="/blog/2025/06-14-sizeof-array/">sizeof array</a>、<a href="/blog/2022/05-07-sizeof-non-static-member/">Size of a non-static member of a class</a></li>
<li><a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2253.html" target="_blank" rel="noreferrer">N2253</a></li>
</ul>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[string_view 傳值]]></title>
            <link>https://blog.mukyu.tw/notes/%F0%9F%A7%B1%20C++/string_view%20%E5%82%B3%E5%80%BC</link>
            <guid>https://blog.mukyu.tw/notes/%F0%9F%A7%B1%20C++/string_view%20%E5%82%B3%E5%80%BC</guid>
            <pubDate>Wed, 28 Oct 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[`std::string_view` 用 傳值 就好，不需要 `const std::string_view&`。
- 語意上它本來就是 view（reference）
- 只有指標 + 長度，傳值時]]></description>
            <content:encoded><![CDATA[<h1 id="string-view-傳值" tabindex="-1">string_view 傳值 <a class="header-anchor" href="#string-view-傳值" aria-label="Permalink to &quot;string_view 傳值&quot;"></a></h1>
<p><code>std::string_view</code> 用 <strong>傳值</strong> 就好，不需要 <code>const std::string_view&amp;</code>。</p>
<ul>
<li>語意上它本來就是 view（reference）</li>
<li>只有指標 + 長度，傳值時 x86-64 直接放進兩個暫存器</li>
<li>傳 <code>const&amp;</code> 反而要先在 stack 建立物件再傳位址（gcc <code>-O3</code> 實測指令更多）</li>
</ul>
<p>小型 trivially copyable struct 同理。</p>
<h2 id="參考" tabindex="-1">參考 <a class="header-anchor" href="#參考" aria-label="Permalink to &quot;參考&quot;"></a></h2>
<ul>
<li>原文：<a href="/blog/2022/06-28-std-string-view-pass-by-value/">std::string_view 函數傳值與編譯器最佳化</a></li>
<li><a href="https://quuxplusone.github.io/blog/2021/11/09/pass-string-view-by-value/" target="_blank" rel="noreferrer">Three reasons to pass std::string_view by value</a></li>
</ul>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[整數型別的坑]]></title>
            <link>https://blog.mukyu.tw/notes/%F0%9F%A7%B1%20C++/%E6%95%B4%E6%95%B8%E5%9E%8B%E5%88%A5%E7%9A%84%E5%9D%91</link>
            <guid>https://blog.mukyu.tw/notes/%F0%9F%A7%B1%20C++/%E6%95%B4%E6%95%B8%E5%9E%8B%E5%88%A5%E7%9A%84%E5%9D%91</guid>
            <pubDate>Wed, 28 Oct 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[# 整數型別的坑

## 倒序迴圈

`size_t` 是 unsigned，`i >= 0` 永遠成立 → 無窮迴圈：

```cpp
for (size_t i = n - 1; i >= 0; --i)  // ❌
for (size_t i = n; i--;)             // ✅ 但不好讀
```

換成有號型別時：

| 型別 | 語意 | 來源 |
| ]]></description>
            <content:encoded><![CDATA[<h1 id="整數型別的坑" tabindex="-1">整數型別的坑 <a class="header-anchor" href="#整數型別的坑" aria-label="Permalink to &quot;整數型別的坑&quot;"></a></h1>
<h2 id="倒序迴圈" tabindex="-1">倒序迴圈 <a class="header-anchor" href="#倒序迴圈" aria-label="Permalink to &quot;倒序迴圈&quot;"></a></h2>
<p><code>size_t</code> 是 unsigned，<code>i &gt;= 0</code> 永遠成立 → 無窮迴圈：</p>
<div class="language-cpp vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">cpp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">size_t</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> n </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">>=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">--</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">i)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  // ❌</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">size_t</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> i </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> n; i</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">--</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;)</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">             // ✅ 但不好讀</span></span></code></pre>
</div><p>換成有號型別時：</p>
<table tabindex="0">
<thead>
<tr>
<th>型別</th>
<th>語意</th>
<th>來源</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>ssize_t</code></td>
<td>byte 數或錯誤值</td>
<td>POSIX</td>
</tr>
<tr>
<td><code>std::ptrdiff_t</code></td>
<td>指標相減的結果</td>
<td>標準庫，C++20 <code>std::ssize()</code> 回傳</td>
</tr>
</tbody>
</table>
<p>偏好 <code>std::ptrdiff_t</code>（標準、可移植）。</p>
<h2 id="int64-t-literal" tabindex="-1"><code>int64_t</code> literal <a class="header-anchor" href="#int64-t-literal" aria-label="Permalink to &quot;`int64_t` literal&quot;"></a></h2>
<p><code>1L</code>、<code>1LL</code> 都不是跨平台的 <code>int64_t</code>（<code>int64_t</code> 在 macOS 是 <code>long long</code>、Linux 是 <code>long</code>），<code>std::min(1L, a)</code> 會因型別不同編不過。</p>
<ul>
<li>✅ <code>static_cast&lt;int64_t&gt;(1)</code></li>
<li>✅ 有意義的常數：<code>const int64_t kMin = 1;</code></li>
<li>❌ <code>INT64_C(1)</code>：型別是 <code>int_least64_t</code>，不保證就是 <code>int64_t</code></li>
</ul>
<h2 id="參考" tabindex="-1">參考 <a class="header-anchor" href="#參考" aria-label="Permalink to &quot;參考&quot;"></a></h2>
<ul>
<li>原文：<a href="/blog/2023/04-11-cpp-array-reverse-access/">C++ 中倒序存取陣列的型別問題</a>、<a href="/blog/2024/05-06-int64t-literal-constant/">int64_t Literal Constant?</a></li>
</ul>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[無窮迴圈的未定義行為]]></title>
            <link>https://blog.mukyu.tw/notes/%F0%9F%A7%B1%20C++/%E7%84%A1%E7%AA%AE%E8%BF%B4%E5%9C%88%E7%9A%84%E6%9C%AA%E5%AE%9A%E7%BE%A9%E8%A1%8C%E7%82%BA</link>
            <guid>https://blog.mukyu.tw/notes/%F0%9F%A7%B1%20C++/%E7%84%A1%E7%AA%AE%E8%BF%B4%E5%9C%88%E7%9A%84%E6%9C%AA%E5%AE%9A%E7%BE%A9%E8%A1%8C%E7%82%BA</guid>
            <pubDate>Wed, 28 Oct 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[C++ 中 沒有 side effect 的無窮迴圈是 UB，編譯器可以假設迴圈會結束。
```cpp
int main() {
    while (1);
}
void unreachable()]]></description>
            <content:encoded><![CDATA[<h1 id="無窮迴圈的未定義行為" tabindex="-1">無窮迴圈的未定義行為 <a class="header-anchor" href="#無窮迴圈的未定義行為" aria-label="Permalink to &quot;無窮迴圈的未定義行為&quot;"></a></h1>
<p>C++ 中 <strong>沒有 side effect 的無窮迴圈是 UB</strong>，編譯器可以假設迴圈會結束。</p>
<div class="language-cpp vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">cpp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">int</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> main</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    while</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> unreachable</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">() { </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">std</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">::cout </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;&#x3C;</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> "why?</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">\n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">; }</span></span></code></pre>
</div><p>clang 15 <code>-O1</code> 會把 <code>main</code> 整個刪掉，直接落到下一個函數，印出 <code>why?</code>。</p>
<p>同理，下面的 Collatz 迴圈會被編成單一 <code>ret</code>，不是編譯器證明了猜想：</p>
<div class="language-cpp vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">cpp</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">void</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> collatz</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">unsigned</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> n</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    while</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (n </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">></span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) n </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> n </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">%</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 2</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> ?</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 3</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> *</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> n </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> :</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> n </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">/</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div><ul>
<li>C++26（P2809）起，條件為常數的 trivial 無窮迴圈（如 <code>while (1);</code>）不再是 UB</li>
<li>gcc、MSVC、clang 11、<code>-O0</code> 都不會這樣</li>
<li>需要無窮等待時，迴圈內放 side effect（I/O、<code>volatile</code>、atomic），或改用 sleep / 條件變數</li>
</ul>
<h2 id="參考" tabindex="-1">參考 <a class="header-anchor" href="#參考" aria-label="Permalink to &quot;參考&quot;"></a></h2>
<ul>
<li>原文：<a href="/blog/2023/02-11-cpp-loop-undefined-behavior/">C++ 有關迴圈的未定義行為？</a></li>
</ul>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Apple Books]]></title>
            <link>https://blog.mukyu.tw/notes/%F0%9F%93%93%20%E9%9B%BB%E5%AD%90%E6%9B%B8/Apple%20Books</link>
            <guid>https://blog.mukyu.tw/notes/%F0%9F%93%93%20%E9%9B%BB%E5%AD%90%E6%9B%B8/Apple%20Books</guid>
            <pubDate>Wed, 15 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[匯出 EPub
1. 把要會出的書籍拖出來（例如拖到桌面）。此時拖出來的東西雖然雙擊後可以從 iBooks 打開，但其實仍然是一個資料夾。
2. 把這個資料夾壓縮成 zip 。
   
2. 把 .z]]></description>
            <content:encoded><![CDATA[<h1 id="apple-books" tabindex="-1">Apple Books <a class="header-anchor" href="#apple-books" aria-label="Permalink to &quot;Apple Books&quot;"></a></h1>
<h2 id="匯出-epub" tabindex="-1">匯出 EPub <a class="header-anchor" href="#匯出-epub" aria-label="Permalink to &quot;匯出 EPub&quot;"></a></h2>
<ol>
<li>
<p>把要會出的書籍拖出來（例如拖到桌面）。此時拖出來的東西雖然雙擊後可以從 iBooks 打開，但其實仍然是一個資料夾。</p>
</li>
<li>
<p>把這個資料夾壓縮成 zip 。</p>
</li>
</ol>
<p><img src="./right-click-menu.jpeg.jpeg" alt="Finder 右鍵選單中的「壓縮」選項" width="250" height="234" loading="lazy"></p>
<ol start="2">
<li>把 .zip 副檔名去掉，就可以拿到 Epub 檔案了。</li>
</ol>
<p><img src="./change-ext-dialog.jpeg" alt="macOS 詢問是否把副檔名從 .zip 改為 .epub 的對話框" width="250" height="216" loading="lazy"></p>
]]></content:encoded>
            <enclosure url="https://blog.mukyu.tw/right-click-menu.jpeg.jpeg" length="0" type="image/jpeg"/>
        </item>
    </channel>
</rss>