C++のinlineはインライン展開するという意味ではない

C++の好きな指定子が inline で、inline は「インライン展開する」という意味ではないというのが好き。

「インライン展開する」という意味で inline を使うとしたら、

#include <stdio.h>
#include <stdlib.h>

inline int fibonacci(int x) {
  if (x <= 1) { return x; }

  return fibonacci(x-2) + fibonacci(x-1);
}

int main(int argc, char **argv) {
   printf("%d\n", fibonacci(atoi(argv[1])));
}

こういう再帰がいるような関数だとインライン展開できずにエラーになるはずである。 実際にはもちろんこれはエラーではない。

仕様を読んだことはないので厳密な定義は知らないが、inline 指定子は、「インライン展開的なことをやっても整合性とれるようにシンボルを定義してくれ」という指示になる。

インライン関数は通常ヘッダファイルに置かれるので、よくある使いかたは、

// h.h

inline int a(int x) { return x + 1; }
extern int b();
// a.cc
#include "h.h"
#include <stdio.h>

int main() {
  printf("%d\n", a(10) + b());
}
// b.cc
#include "h.h"

int b() { return a(10); }

こんな感じになるだろう。

ここで、inline 指定子がないとどうなるかというと、

// h.h
int a(int x) { return x + 1; } // inlnie をなくす
extern int b();
g++    -c -o a.o a.cc
g++    -c -o b.o b.cc
cc   a.o b.o   -o a
/usr/bin/ld: b.o: in function `a(int)':
b.cc:(.text+0x0): multiple definition of `a(int)'; a.o:a.cc:(.text+0x0): first defined here
collect2: エラー: ld はステータス 1 で終了しました
make: *** [<ビルトイン>: a] エラー 1

a.o と b.o の両方に関数aの実態ができてしまって multiple definition のエラーになる。

inline 指定子は、このmultiple definitionを起こさないでね、というのが仕様で、この仕様があることによって、インライン展開するような使いかたをしても問題が起こらない、という状況にできる。

じゃあこれ static とどう違うの?という話になるが、

// h.h
static int a(int x) { return x + 1; } // inline でなく static
extern int b();
g++    -c -o a.o a.cc
g++    -c -o b.o b.cc
cc   a.o b.o   -o a # OK!

staticは、ファイルローカルな関数を意味して、同じ名前でファイル毎に定義が違っても構わない。一方、inline は同じ名前で定義された変数は、全てのファイルで同じ定義になってないといけない、という違いがある。

#include <stdio.h>

YOUR_SPECIFIER int a(int x) { return x+1; }
extern int b();

int main() {
  printf("%d\n", a(10) + b());
}
// y.cc
YOUR_SPECIFIER int a(int x) { return x+1; }

int b() { return a(10); }

これは static でも inline でも動作は変わらない

$ g++ -DYOUR_SPECIFIER=static   -c -o x.o x.cc
$ g++ -DYOUR_SPECIFIER=static   -c -o y.o y.cc
$ cc   x.o y.o   -o x
$ ./x
$ 22

$ g++ -DYOUR_SPECIFIER=inline   -c -o x.o x.cc
$ g++ -DYOUR_SPECIFIER=inline   -c -o y.o y.cc
$ cc   x.o y.o   -o x
$ ./x
$ 22

ところが、このように a(int x) の定義を複数のファイルで違う定義にしてしまうと違いが出る。

// x.cc
#include <stdio.h>

YOUR_SPECIFIER int a(int x) { return x+100; }
extern int b();

int main() {
  printf("%d\n", a(10) + b());
}
// y.cc
YOUR_SPECIFIER int a(int x) { return x+1; }

int b() { return a(10); }
$ g++ -DYOUR_SPECIFIER=inline -O2 -fno-inline   -c -o x.o x.cc
$ g++ -DYOUR_SPECIFIER=inline -O2 -fno-inline   -c -o y.o y.cc
$ cc   x.o y.o   -o x
$ ./x
220
$ g++ -DYOUR_SPECIFIER=static -O2 -fno-inline   -c -o x.o x.cc
$ g++ -DYOUR_SPECIFIER=static -O2 -fno-inline   -c -o y.o y.cc
$ cc   x.o y.o   -o x
$./x
121

この場合、staticはきちんと定義されていて、どの環境でもこの通りに動くが、inlineを付けたほうは、値が何になるかはわからない。(仕様は見てないので未定義動作かどうかは知らない)

じゃあ inline より static のほうがミスが起こりづらくていいんじゃない?とずっと思ってたのだけど、去年くらいからいややっぱ static inline はインライン展開されなかった時に実体が意味もなく複数できてしまって.textサイズ無駄にでかくしてるよなぁ…と思うようになりなんも考えないでstatic inlineするようなことはやめました。

$ # static
$ ls -l x
-rwxr-xr-x 1 tanakmura tanakmura 15568  6月 23 00:54 x


$ # inline 
$ ls -l x
-rwxr-xr-x 1 tanakmura tanakmura 15528  6月 23 01:06 x

みんなも適切にinlineを使いましょう。

参考 : https://qiita.com/kktk-KO/items/075ce9a784d5d8296d53

(タイトルに反して staticinline の違いしか書いてない。static inlineinlinestaticの違いは…私もよく分からないのでみんなで調べよう!)

(inline 指定子の仕様にはインライン展開するって書いてあるか、全然書いてないかも知らないです。何も知らない。知ってること何もなかった)

Arm laptop

なんかいいやつないかな → ない

Cortex-X2 とか X3のが欲しいのだった。もちろん X4 でもいい。このぐらいになればもうx86に追い付いて普通に使えるのではという気がしたので。

Androidはある。

Wikipediaを見れば一覧あったわ。

https://en.wikipedia.org/wiki/List_of_products_using_ARM_processors

Surface のは Qualcomm ので、残念ながらCortex-X1らしい。

手元のスマホはSnapdragon 888で Cortex-X1 だった。(Snapdragon 888 は Gen8 とは違うという学びがあった)

新しめの Arm Chromebook

どちらも Cortex-A76。まあCortex-A76よりはN100のほうが使いたいかな。

あと調べてて Android のシェア No1 は Mediatek になってるという学びもあった。

https://www.mediatek.jp/products/chromebook-tablets/tablets "トップメーカーから選ばれる MediaTek Android タブレットで業界 第。"

コンピュータ用語と日常生活

集合住宅の屋上にある水道タンク(今調べた:貯水槽と呼ぶようだ)を見るたびに思うのだけど、あれはコンピュータ知らない人は、あの概念を何と呼ぶのだろうか。

需要が発生するごとにポンプを動かしてると瞬間最大需要を賄えるだけの巨大なポンプが必要になるが、瞬間最大需要が必要な時間はあまりない。

そこで、平均的な負荷を賄えるポンプを設置しておいて、それを使って水を屋上に一定量蓄えておく。需要が増えたら貯水槽から重力を使って水を流すというようになっている。
これによって、平均的な負荷を賄えるだけのポンプで、全住宅の需要を賄う水道を実現している。

この概念は、コンピュータやってる人には、「水をバッファリングして負荷を平滑化してる」と言えばそれなりに伝わると思う。そうでない人は"バッファリング"をどう理解してるんや?
分野毎に、バッファリングの概念を発明してるんだろうか?「ある程度蓄えることで、スパイクを滑かにできる」っていうのってコンピュータの外に出ても一般的な概念だと思うが、なんて言ってるんや?


似たようなのはぼちぼちあって、「タスクの依存関係」とかも、「あれこれってコンピュータ以外の人に通じる言葉だっけ?」ってなりがち。


「キューする」とかはアメリカだとqueue hereとか書かれてるので通じそう。


https://question.realestate.yahoo.co.jp/knowledge/chiebukuro/detail/1479764104/ 知らなかったが貯水槽は地下にもバッファがあるらしい。

昔貯水槽に腐乱死体がある事件あったよな…と思い出して調べたら定期的にある事件っぽかった。

土地立ち退きバッファリングとスループット

家の前の道が、おそらく道路拡張用に確保してあって、歩道が結構広いのだけど、やっぱりなかなか立ち退かない人がいるのか、そこから出っぱってる家がある程度ある。

確保しはじめてから、おそらくもう数十年たっていて、歩道確保してるところの建物も全然新しくない。こういうの、役所は大変だなと思ってたけど、しばらく毎日見てて最近はそうでもないかもな、と思いはじめた。

大事なのは、役所と立ち退かない人、どちらが先に寿命くるかで、やっぱ大体の場合人間の寿命のほうが先にくるよね。都市計画なんて数十年単位でやるわけで、立ち退かない人が20年立ち退かないのなんて、巨大な計画の一部にしかならない。数十年かけて、寿命が来て、相続した子孫がめんどうだから役所に売却してそれで終わり。

立ち退かなくて工事すすまない、みたいな事象って、世界中あちこちにありすぎて、もう十分バッファリングされてるはずなんだよな。
つまり、強制的に立ち退きなんかやらなくても、寿命を迎えて売却するという人が確率的に発生する、それが十分な数発生してて、工事スループットとしては十分に出るという状態なんじゃないか。
むしろ急に積極的に立ち退く人が大量に出たりすると工事が間にあわなくて、土地を役所が無駄に確保し続けないといけなくて固定資産税入らなくなるから、役所に不利とかいう可能性もある。

Linuxの実行環境のisolationをもうちょっとちゃんとする今年は

いままでpip実行するたびに、「これどこかのsetup.pyに一行でもid_rsaとかfirefoxのprofileデータをどこかにアップロードするコード混じってたら終わりだよな」と思ってたけど、

https://pytorch.org/blog/compromised-nightly-dependency/

いよいよそういうことが起こってきたので、なんとか対応したほうがいいという気持ちになった。今年中に使用感を悪化しない範囲でどこまでできるかを探りたいと思いますね。

  • ブラウザを別UIDで実行する

firefoxのデータに自由にアクセスできたらMFAとか意味ないんだよなあ…

ブラウザのデータを別プロセスから読みたいとか、ブラウザにパイプ繋げたりとかしたい場合はないので、別ユーザにして、isolationすべきという気がする。

firefoxだけ起動できる UID を作って、その UID で firefox 起動コマンドを受けて起動するデーモンを入れておくとかする。

waylandはshm経由で画像データやりとりするので、ブラウザで今表示してるものが別プロセスから読まれるのだけ回避できないかも。

  • sudo 運用をなんとかする

知らないプロセスが勝手にsudoするような事態があれば他の対策が全部無駄になるので、あずかり知らぬところでsudoが通るみたいな事態だけは絶対避ける。

sudo 最初はターミナルごとにパスワード要求にする。パスワードではなくてYubikeyを要求するとかがベスト?(yubikeyは必ずタッチしないと通らないので)

sudo やめて polkit ちゃんと設定方法を覚えるべきという気もするが、polkitでうまく運用できる気がしないのでやらないかも。

  • SELinux 使いかたちゃんと覚えて妥協ラインを探す

pip とか cargo とかで取ってきたコードを実行するときはちゃんとisolateした環境で実行すべき。

プロセスごとにアクセスできるリソースを制限できればよくて、SELinuxちゃんと覚えればできるはずや。

aurでインストールしたようなのはどうしたらいいですか?どうしたらいいですかね…

  • Yubikeyの使いかたマスターする

証明書、鍵とかなんとかそういうのをちゃんと理解する(まだあんまり理解してないので書けることはない)

ssh も yubikey にする。それで id_rsa コピーされる心配はなくなる

今のLUKSはfido2とか使ってpassphrase消すと二度と設定変えられなくなるが、これUIというかsystemd-cryptenrollの問題でほんとはなんとかできるでしょ。