にゃははー

はへらー

AoSとSoAなflat_map

std::mapを線形配列に落とし込むことで、イテレータ走査やメモリレイアウトを効率化したflat_mapについては以前説明しました。

flast.hateblo.jp

当時私が実装したflat_mapはArray of Structure(AoS)形式の実装で、構造体を線形配列に配置するものでした。これはキーと値がメモリ上で並んだ位置に配置されるので、キーから検索した直後に値を使う場合にはキャッシュに載っている可能性が高くなる利点があります。

続きを読む

平らな地図、もといflat_map

この記事は C++ Advent Calendar 2021 の8日目です。

ブログもAdvent Calendarも、ものすごく久しぶりになってしまいました。あの頃カラオケで規格書を開いて語り合っていた面子も見なくなり、最近の新しい仕様はよくわからないです。歳をとったものです。

続きを読む

謎の用語niebloid

cppreference.comは随所に様々アノテーションがついていて大変便利だ。例えば(since C++17)といった感じでこれはC++17以降に登場した定義とかそういうのがひと目でわかる。さっき20での変更に何があるのか適当に眺めていたところ、<algorithms>の変更でConstraind algorithmsというのを見つけた。これはいわゆるRange TSと呼ばれていたもので、Boost.Rangeの標準化みたいなもの(のはず)だ。

よくよく見てみると、これには(niebloid)という見慣れないアノテーションがついている。全くわからない。他の(concept)とかは意味がわかる。これはそのままだ。

適当にぐぐってみるとものすごくヒットが少ない。とはいえ検索結果で目につくのはなんと言ってもEric Nieblerだ。この人はBoost.Rangeのメンテナで、Range TSの担当(?)だ。なるほどなんとなく察しがつく。

どうもniebloidというのは彼が作った造語で、これらはADLを徹底的に排除した関数呼び出し形式で扱えるなにかを指すらしい。 言いたいことはわかるがしかしあまりに唐突すぎる言葉なのでcppreference.comにも何かしらの説明がほしい... cppreference.com内で検索してもヒットしないのはいただけない

ちなみにNieblerは ニーブラー と発音するっぽいので、おそらくniebloidは ニーブロイド と発音するのだろう。

msgpackのデバッグをするための何か

msgpackのデータはあるんだけどなんかズレてたりしてデシリアライズ出来なくて困った困ったみたいなとき、目デシリアライズするのも(でかいと)ツライし、そうでなくてもデバッグしてる間に中身を見ようとしてもVSのデフォルトのビジュアライザだと中途半端でつらいものがあった

一応ブラウザで動くビジュアライザもあるらしいがbase64にしないといけないっぽいし、でかいデータでも大丈夫なのかな、、とか、(多分)オフラインだけどちょっと機密データのデバッグには抵抗感がある http://sugendran.github.io/msgpack-visualizer/

Visual Studioのデバッガは優秀(真顔)だけどvisualizerもmsgpack的にはちょっと足りない

つくったもの

msgviwer

https://github.com/Flast/msgviewer

とりあえずバイナリデータをツリー状にして可視化する

単にツリーで見えても修正とかだるかったからオフセットも見えるようにしてる

Qtで作ってるから大体の環境で動くはず

ビルド方法とかドキュメントとか無いのはなんとかしないといけない(使命感)

msgpack-vs-visualizer

https://github.com/Flast/msgpack-vs-visualizer

Visual Studioのデバッガで配列とか中身全部みれるようにするやつ

こっちもドキュメントとか全然ないけど雰囲気でがんばって(適当)

とりあえず配列のようなやつらは全部ちゃんと見えるようになった

余計な via とか見えてるのは気が向いたらそのうちなんとかしたい

allocaをinline関数で使うと危険である?

“allocaをinline関数で使うと危険である"という要旨のメールがoss-securityに流れてて、これは一体どういうことだ…と思った。

長い文章でも無いしそんなに難しくもないが、どうやらGCCオプティマイザの展開順に問題があるようだ。

http://www.openwall.com/lists/oss-security/2017/04/10/18

曰く、alloca(本文ではC(99)のVLAを指していた)を見つけるとGCCはそれを__builtin_allocaに展開した後、そのinline関数をインライン展開するので、ループ中で使うとスタックをガンガン持ってかれるということだった。 allocaは任意のスコープではなく、関数スコープからの離脱でのみスタックの巻き戻しを行うので、ループ本体を一巡したあとに本来巻き戻って欲しいスタックが巻き戻らず、次のallocaが行われてスタックが枯渇する脆弱性になると指摘している。

試しにMLに張られたコードに足りない部分を補完してバイナリを見てみたが、どうにも普通に巻き戻しはしているように見える。 -Oから既にインライン展開は行われるが、いくつかの最適化レベルを眺めてもやはり巻き戻しているように見える。

https://godbolt.org/g/fiofnf

なにか別の要因があるのだろうか…

スレッドアンセーフなshared_ptr

多分みなさんはstd::shared_ptrを使ってるとシングルスレッドで使うんだからスレッドアンセーフでいいのにとか思うことが良くありすぎて再実装したくなると思います。ならない方はなって下さい。設計が悪いと言う人はrecursive mutexを今後使わないで下さい。

はい。

で、libstdc++にはそういう拡張があるらしいです。 ドキュメントにはないけど。

基本的に使い方はstd::shared_ptr(と関連するもの)と同じだけど、第二テンプレート引数を受け取る点が違ってて、このテンプレート引数でMT-safe-nessを指定する感じになっている。

bits/shared_ptr_base.h melpon.org

執筆時点で定義されているのは3通り

  • 完全にunsafe
  • ミューテックスを使ってアトミックにカウント
  • アトミックカウンタを使ってアトミックにカウント

ext/concurrence.h

デフォルトのポリシーはスレッドサポートがあるかどうかとCPUのアトミック命令のサポートがあるかどうかで変わるぽいです。

なので、明示的にstd::_S_singleを渡せばMT-unsafeなshared_ptrが手に入ります。 ヤッター!

演算子における引数の評価順と副作用

年も瀬だというのにTwitterで規格書たちが騒いでいたのは記憶に新しい(?)と思うけど、自分もC++11(とちょっとあと)までしか読んでなかったせいで、いろいろ時代の潮流に取り残されている感じがあったのでちゃんと自分で調べましたっていう話。

事の発端と反応はおおよそこちらにまとまっているので参照されたい。

paiza.hatenablog.com

現時点でC++17として正式に規格が発行されたわけじゃないので本文中ではC++1zとし、最終的にISとなった場合にさらに追加で変更されている可能性もありますので、注意してください。

続きを読む