タグ

ブックマーク / cpplover.blogspot.com (29)

  • C++のfilesystemライブラリが膨大すぎる

    C++17の参考書はほぼ書き終えて、あとはfilesystemライブラリの解説を残すだけになっている。 EzoeRyou/cpp17book: textbook for C++17 ファイルシステムライブラリは、ext4とかbtrfsのようないわゆるファイルシステムに対するライブラリではなく、ディレクトリとファイルに対する操作を提供するライブラリだ。具体的にはファイルパスの文字列処理や、ファイルのコピーやリネーム、ディレクトリ構造のトラバースといった雑多なファイルシステム操作を提供する。 C++のファイルシステムライブラリは、原則としてPOSIX互換になっている。POSIXの規定するライブラリをモダンなC++風のライブラリとして設計したものだ。例えば、カレントディレクトリにあるファイルをすべて表示するプログラムは以下のように書ける。 #include <filesystem> #inclu

  • C++プログラマのレベル10

    レベル0 C++とかいう、Cにヘンテコな機能を付け加えた言語があることはしっているが、ワケ分からんので勉強する気にならない。 Cの何が不足なのか分からない。 C++についてググったり、入門書を読んだりしてみる。文法はCに後から無理やり付け加えた感じだ。 でも文法がわかりにくすぎる。 レベル2 vectorとか便利すぎて涙がでる。もういちいちrealloc()を呼び出さなくてもいいんだ。でもイテレーターとかいうのが、ワケ分からんので、ポインタを使っている。 構造体の中に関数を書けるのは便利かもしれない。すくなくとも、わざわざ構造体のポインタを引数に渡さなくてもいいわけだ。 レベル3 テンプレートが分からなくて挫折中。テンプレートがわかれば、STLがもっと分かるようになる気がする。でも、いい参考書が見つからない。 継承とか仮想関数も便利だと気がつく。namespaceも地味に便利だ。 レベル4

  • GCCの実験的なfilesystemを使う方法

    C++17には<filesystem>が追加される。GCCは実験的な実装として<experimental/filesystem>を実装している。 これを使えば、例えば以下のようにディレクトリを列挙できる。 #include <experimental/filesystem> namespace fs = std::experimental::filesystem ; int main() { fs::directory_iterator iter("/usr/bin"), end ; std::copy( iter, end, std::ostream_iterator<fs::path>(std::cout, "\n") ) ; } GCCのfilesystemは、実験的な実装であるので、ヘッダーファイルが<experimental/filesystem>であることに加え、デフォルトでは

  • GCCのSVN trunkをビルドする方法

    GCC 7がC++17のコア言語機能を完全に実装したので、ようやく参考書のサンプルコードが検証できるようになった。 C++ Standards Support in GCC - GNU Project - Free Software Foundation (FSF) しかし、GCC 7はまだリリースされていない。少し試すだけならばwandboxが使えるが、格的に使うにはローカルにほしい。 [Wandbox]三へ( へ՞ਊ ՞)へ ハッハッ そこで、GCCを自前でビルドすることにした。ビルドは以下の手順に従う。 Installing GCC - GNU Project - Free Software Foundation (FSF) GCCのコンパイルに必要なソフトウェア Prerequisites for GCC - GNU Project - Free Software Foundat

  • rootが無効化された環境でsshfsで権限の必要なファイルを変更する方法

    sshfsは便利だ。リモートのファイルシステムをローカルのファイルシステムにマウントして扱うことができる。これにより、ローカル側のGUIのファイルシステムビューワーやエディターを使った温かみののある手作業による管理ができる。 ところで、Ubuntu Serverではrootが無効化されている。そのため、sshfs root@host:remote_path local_path はできない。代わりに、root権限が必要な操作はsudoを使って行う。しかし、sshfsではsudoができない。一体どうすればいいのだろうか。 試していないが、調べたところ、sftp_serverを指定する方法で行けるようだ。 まず、sudocredentialをキャッシュさせるために、ssh軽油でsudo -vを実行しておく。 そして、以下のようにsshfsでsftp-serverを指定する。 sshfs us

  • プログラミング言語基礎勉強会で発表した

    プログラミング言語基礎勉強会 sponsored by @wantedly UIターン - connpass 上記の勉強会で発表してきた。今回の発表は、C++17の標準ライブラリを軽く説明した。 発表に使用したスライド資料はGitHubに上げてある。 EzoeRyou/cpp17lib-slide: 勉強会のスライド資料 発表者が全員濃かったので、他人の発表はあまりよくついていけなかった。 最後に地方と都内で仕事をすることについてというテーマでパネルディスカッションがあったが、いかんせんテーマが技術的なものではないので、極めて一般なこと、例えば地方は地代が安いだの、都内は通勤ラッシュがひどいだのといった、誰でも言えるようなことしか話せず、せっかくあの人間を前に集めて議論する内容としては非常にもったいなく感じた。一体何を考えて、あの人選に対してあんな陳腐なテーマを設定したのか謎だ。 その後懇

  • ループカウンタを64bitにしたり、 バッファのサイズを定数にしたらパフォーマンス激落ちなんだけど何で?

    ループカウンタを64bitにしたり、 バッファのサイズを定数にしたらパフォーマンス激落ちなんだけど何で? c++ - Replacing 32bit loop count variable with 64bit introduces crazy performance deviations - Stack Overflow stackoverflowで、興味深い質問が行われている。 簡単にまとめるとこうだ。std::uint64_t型の配列の各要素にx86-64のpopcnt(1になっているビット数を数える命令)を適用したい。 コードの肝心の部分を書くと、以下のようになる。 for (unsigned i=0;i<size/8;i+=4) { count+=_mm_popcnt_u64(buffer[i]); count+=_mm_popcnt_u64(buffer[i+1]); coun

  • curl | bashをサーバーサイドで判定する方法

    Detecting the use of "curl | bash" server side | Application Security ソフトウェアをインストールするとき、シェルスクリプトを実行するのはよくあることだ。しかし、そのシェルスクリプトが他人のリモートサーバーでホストされていた場合、curl | bashするのは危険だ。まともなユーザーは、curl | bashする前に、まず中身を確認して、悪意がないことを確かめるものだ。 しかしもし、サーバー側がwgetやcurlといったツールとブラウザーを判定して、それぞれ別のコードを返した場合どうか。ユーザーが見るのは囮のシェルスクリプトだ。 しかし、それではcurlやwgetを利用してシェルスクリプトをダウンロードするユーザーは騙せない。しかしもし、curlcurl | bashを判定することができたらどうか。実は、できるのだ。 c

  • 本の虫: rvalue reference 完全解説

    目的 この記事は、C++0xのrvalue referenceを完全に解説せんとする目的を以て書かれた。サンプルコードは最小に留め、エラー処理等は省いた。この記事さえ読めば、今日からrvalue referenceを恐れることなく使う物のC++0xプログラマになれるだろう。 lvalueとrvalueについて Cの時代では、lvalueとrvalueの違いは、代入演算子の左側か右側かという違いだけであった。つまり、left hand value, right hand valueの略である。従って、訳語も、左辺値、右辺値であった。C++においては、これはもはや正しくはない。従って、右辺値、左辺値というのも、誤訳である。それ故に、ここでは、これ以上、左辺値、右辺値という名称を使用しない。 誤解を恐れずにいえば、lvalueとは、明示的に実体のある、名前付きのオブジェクトであり、rvalue

  • C++11による高精度なカウンター

    パフォーマンスを計測するには、高精度なカウンターが必要である。このカウンターは、決まった周期で値が刻まれることにより、正確な経過時間の計測ができる。 最近、GNU/Linuxに移行したので、またどうもこの環境に慣れていない。ともかくGNU/Linuxで高精度なカウンターを使う方法を調べることにした。つまり、Win32 APIでいうところの、QueryPerformanceCounterのようなものがほしい。 まず見つかったのはPOSIXのclock_gettimeだ。これを使えば、ナノ秒単位での分解能が得られる。ただし、timespec構造体が非常にややこしい作りになっている。秒とナノ秒に分かれているのだ。これは面倒だ。こんなインターフェースでは間違えたコードを書いてしまいそうだ。 また、未だにGNU/Linux環境におけるライブラリのリンク方法がよくわからないのだが、どうもclock_g

  • C++11の時間ライブラリは美しさを追求したあまり、かえって使いにくくなっているのではないか

    C++11の時間関係のライブラリは、非常に美しい設計をしている。 まず、経過時間そのものを表すdurationがある。Cライブラリでいえば、time_tの値の単位を指定するクラスだ。Cライブラリでは、time_tの値は秒であったが、C++では、単位を指定できるのだ。 durationでは、単位ライブラリであるratioを使って、秒、ミリ秒、マイクロ秒などといった時間単位を表現している。 秒 std::chorno::seconds ミリ秒 std::chrono::milliseconds ナノ秒 std::chrono::nanoseconds 時 std::chrono::hours それ以外の、独自の刻みがほしいとしても、簡単に作成できる。 4分33秒 using four_minutes_thirty_three_seconds = std::chrono::duration< l

  • C++11の時間ライブラリ: chrono

    <chrono>は、C++11で追加された時間ライブラリである。 単位時間を扱うためのduration、起点からの経過時間を扱うためのtime_point、現在の起点からの経過時間を取得するためのclockからなる。Cの標準ライブラリのtime_tとtime(), clock_gettime()を置き換えることが出来る。日付機能は含まれていない。 duration 時間について考える。一時間は60分である。1分は60秒である。1秒は1000ミリ秒である。 単位の異なる時間の値を相互に変換するのは、簡単な計算だ。 unsigned int min_to_sec( unsigned int min ) { return min * 60 ; } しかし、実引数minに渡される値の単位が分であることを保証する方法はない。間違えたとしても、コンパイルエラーにはならない。 chronoでは、時間単位

  • GCCの最適化オプション

    郷に入っては郷に従えというが、GNU/Linuxのプログラミング環境にはまだまだ慣れない。とりあえず今のC++執筆作業には、最新のClangでコンパイルできればそれで用が足りるので、Clangのビルドが楽なGNU/Linux環境は悪くない。欲を言えばlibc++もまともに動くようになってほしい。Ubuntu 12.10でlibsupc++を使ってlibc++をビルドしてみたところ、RTTI周りのABIに問題があるらしく、virtual関数呼び出しすらできなかった。 しかし、GNU/Linuxにおけるプログラミングはどうにも学ぶことが多すぎる。GNUのgdbの使い方もそろそろ覚えたいし、Autotoolsの使い方も覚えたいものだ。幸い、GNU/Linuxで一般的なテキストエディターであるVimは、特に何も学ばなくても使えるので楽だ。たかがテキスト編集作業に、多数のキーボードショートカットを

  • なんでGCCはa*a*a*a*a*a を (a*a*a)*(a*a*a) に最適化できないの?っと

    c - Why doesn't GCC optimize a*a*a*a*a*a to (a*a*a)*(a*a*a)? - Stack Overflow 俺は科学技術計算の数値計算の最適化をしてたんだけどさ。GCCはpow(a, 2)をa*aにしてくれるんだな。うん。で、pow(a, 6)は最適化されずに、ライブラリ関数であるpowを呼んじゃうんだ。パフォーマンス的に最悪。(Intel C++ Compilerはpow(a,6)のライブラリ関数呼び出しを消し去ってくれるんだけどな) どうもよくわからんのが、pow(a, 6)をa*a*a*a*a*aで置き換えて、GCC 4.5.1をオプション"-O3 -lm -funroll-loops -msse4"で使ったら、mulsd命令を5個使う。 movapd %xmm14, %xmm13 mulsd %xmm14, %xmm13 mulsd

  • C++11参考書の公開:C++11の文法と機能

    C++11の参考書をGitHubで公開する。 GitHub: EzoeRyou/cpp-book GitHubからzipでダウンロード GitHub Pagesでの閲覧:C++11の文法と機能 序 書はC++11のコア言語の文法と機能を、標準規格書に従って解説したものである。正式なC++規格書として発行された後の、ひとつ後のドラフト規格、N3337 を参考にしている。ドラフト規格を参考にした理由は、正式なC++規格書は、個人での入手が煩わしいためである。読者に入手が困難な資料を元に記述された参考書は価値がない。そのため、読者が容易に入手できるドラフト規格のうち、正式なC++規格書とほとんどかわらないN3337を参考にした。 書の対象読者は、C++を記述するものである。C++実装者ではない。そのため、サンプルコードを増やし、冗長な解説を増やし、C++コンパイラーを実装するための詳細な定義

  • C++03とC++11の違い: テンプレート編

    京都C++勉強会の宣伝のために、C++03とC++11の違いを、少しづつ解説することにした。 今回は、テンプレートについて、C++03とC++11/14の違いを取り上げる。 C++11では、export機能が廃止となった。 exportは、実装例が極めて少なかったために、C++11では廃止となった。 この変更による互換性の問題は、ほとんどないだろう。というのも、export機能自体が使われていなかったのだから。 C++11では、入れ子となったテンプレートの連続したアングルブラケットの間に、空白文字を挟む必要がなくなった。 template < typename T > struct S { } ; // C++03では違法 // C++11では合法 S<S<int>>> s ; C++03では、右シフト演算子、operator >>と文法上曖昧になるため、必ず空白文字を挟まなければならなか

  • Linus Torvals、クソコードにブチギレ

    Linux-Kernel Archive: Re: [GIT] Networking Linus TorvalsがGCCの独自拡張を使った整数演算のオーバーフロー検知コードがあまりにクソすぎるためにブチギレしている。 On Wed, Oct 28, 2015 at 3:32 PM, David Miller <davem@xxxxxxxxxxxxx> wrote: リリースサイクルのこの後半に入れるのはちょっと怖いと思われるかもしれないが、小規模なドライバーの修正をあちこちに施しただけだよ。 マジかよテメーら、こりゃクソだ。 コンフリクトはGCCの新しいクソヘッダーファイルのせいなんだが、俺がブチギレてるのはそこじゃなくてこいつがクソなせいだ。 net/ipv6/ip6_output.cの以前のコードはこれだ。 mtu -= hlen + sizeof(struct frag_hdr);

  • cpで大量のファイルをコピーした(4億3200万件、39TB)

    GNUのcpを使って大量のファイルをコピーしたところ、cpの設計上の問題で、極めてコピーが遅かったというお話。 My experience with using cp to copy a lot of files (432 millions, 39 TB) よう。俺は最近、大量のファイルをコピーする必要があったんだが、UNIXは20年もやってきた俺の経験からも、cpの挙動には驚かされたし、俺の意見はコミュニティに共有されるべきだと思う。 環境:古いDellのサーバー(2コア、初期メモリ2GB、追加して10GB、Ubuntu Trusty)と、新しいDellのストレージ格納機(MD 1200)にある、12個の4TBディスクでRAID 6が設定してあって、全体で40TBの要領を持ち、二つのドライブが同時に失敗しても問題ない環境。サーバーは遠隔地バックアップに使われていて、ディスクへの書き込みし

  • fork()は失敗するんだぜ、覚えときな

    fork() can fail: this is important あー、fork()のことね。プロセスがもっとプロセス作るためのやつな。いや、他にもプロセス作る方法はあるけどな。ま、面白い話がもうひとつあるから聞かせてやるよ。 forkは失敗するんだぜ。分かってるか? マジで分かってるか? マジだぜ。forkは失敗するもんだ。mallocと同じさ。失敗することもある。そんなに頻繁にってわけじゃないけどさ、でも失敗したら、無視できっこないぜ。ちっとは脳みそ働かせなきゃならん。 forkが0を返したら、そいつは子プロセスで、親なら正数を返すってことは、みんな知ってるよな。その値は子のpidだ。こいつを保存しといて、あとで使うってわけだ。 失敗を確認しない場合どうなるか知ってるか? そうだよ。お前多分、"-1"(forkのエラー通知)をpidとして扱ってるんだろ。 さて、問題の始まりだ。

  • Linuxカーネルのバグをgit bisectで特定する話

    Odd Bits - Tracking down a kernel bug with git bisect Linuxカーネルのバージョンを3.15に上げたところ、Docker内でのsuやrunuserが謎のシステムエラーで動かなくなった。カーネルのバージョンを3.14に下げると問題なく動作する。明らかにカーネルが影響を及ぼしている。 よろしい、ならばgit bisectだ。git bisectは良いコミットと悪いコミットの間をバイナリサーチして、問題を引き起こしたコミットを見つけてくれる。 しかし、Linuxカーネル3.14と3.15の間には、約15000件のコミットがあるので、git bisectを手動で回すのは現実的ではない。 git bisectには、自動化のための仕組み、git bisect runがある。これは、コミットをチェックアウトした後に、自動でスクリプトを実行して、現在