忍者ブログ
  • 2024.03«
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • » 2024.05
[PR]
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

【2024/04/26 04:04 】 |
gccリンカの謎
gccの-lオプションが効かない時があるのでその原因を確かめてみた。


$ gcc  pp4.c pp.c pp2.c
/tmp/ccj9EogJ.o: In function `func':
pp2.c:(.text+0x7): undefined reference to `link2'
/tmp/cchGaury.o: In function `main':
pp.c:(.text+0x11): undefined reference to `link1'
collect2: ld はステータス 1 で終了しました

こんなソースがある場合、link1とlink2を含むlibpp3.soで解決する必要がある
当初、ソース1個以上指定した後の-lオプションのみが有効かと思いきや
リンクメッセージがないと-lが効かないという話を教えてもらったので試してみた。

$ gcc  pp4.c -l pp3 pp.c pp2.c
/tmp/ccj9EogJ.o: In function `func':
pp2.c:(.text+0x7): undefined reference to `link2'
/tmp/cchGaury.o: In function `main':
pp.c:(.text+0x11): undefined reference to `link1'
collect2: ld はステータス 1 で終了しました

あら、ほんとだ。pp4.cはlink1もlink2も依存していないため
これでもエラーが起こる・・・。

$ gcc  pp4.c pp.c -l pp3 pp2.c


では、link1に依存するpp.cの後に-l pp3を移動させると
エラーはなくなった~

てっきり
/tmp/ccj9EogJ.o: In function `func':
pp2.c:(.text+0x7): undefined reference to `link2'
みたいなのが出ると思ったのだけどそうでもないらしい。
つまり・・・
-lオプションは最後に書けということですなぁ。

バージョンによっては直ってるgccもあるらしい。

拍手[0回]

PR
【2013/02/16 20:23 】 | C/C++ | 有り難いご意見(0)
cout vs printf (2)
なぜ、coutのほうが遅いのか?

どうやら double型が特に遅いみたいである。

で、かくかくしかじか辿っていった結果。

一因がnum_putクラスが遅いことが分かった。

num_putのdo_putオーバーライド

class my_numput : public std::num_put<char>
{
protected:
iter_type do_put(iter_type out, ios_base& str, char_type fill, double val) const
{
char buf[50], *bufp = buf;
sprintf(buf, "%g", val);
copy(buf, buf + strlen(buf), out);

return out;
}
};


localeにnum_putを追加

loc = new locale(locale::classic(), new my_numput);
cout.imbue(*loc);


●実行方法1~3で計測してみることにした。
実行方法1

cout << d ;


実行方法2

char buf[50], *bufp = buf;
sprintf(buf, "%g", d);
fputs(buf, stdout);


実行方法3

fprintf(stdout, "%g", d);


結果(ms)

実行方法1(改良後←改良なし)
0.836←0.992

実行方法2
0.768

実行方法3
0.652


情報整理
・num_putが遅いことには間違いない。
・coutは doubleを置換する場合、try catchを行っている。
・coutのostream の出力方法は4×nバイト または1バイトのみである。
・coutのostreambufの出力方法はnバイト または1バイトのみである。
・coutのnum_putの出力対象はchar型のiter_typeなので出力方法は1バイトのみである。
・coutはostreambufでバッファを抽象化し、osteramで循環キューを抽象化している。

結論
coutまわりはクラスが立て込んでいて、ostreambufにフォーマッタがあればいいが
フォーマッタはostreamはlocaleに散らばっている。
これらはostreamが使うワーク領域がostearmbufが管理するワーク領域が
異なっていることに起因しているのかもしれない。
ただし、num_putの中身がどうなっているのか未確認のため怪しい。
また、printf系はバッファを素直にI/Oにしているため
FILEポインタのみを通しているのに対し、writerと媒体の距離が近いのに対し
cout系はostreamからnum_putを経てostreambufの間を1バイトずつ細切れで渡していってる模様。
writerとバッファの距離は遠そうなイメージ?

そんなこんなで、よっぽど最適化されるようにならないと
関数を読んでるだけのprintf系に追いつくのは厳しいと思われる。
きっとjavaの初期のころってこういう課題をなんとかインラインになるように
頑張ったんだろうなと。

しかし、C++の場合はジェネリックはテンプレート頼みだし
coutなんて標準ライブラリだからインラインにする前に
コンパイル済みの関数に紐づくんじゃないかなぁと。

拍手[0回]

【2013/01/06 18:12 】 | C/C++ | 有り難いご意見(0)
cout vs printf
cout と printfの速さを比較してみた。

cout は遅い・・・

endlが遅い要因という話が多いので抜いてみても遅い・・。

拍手[0回]

【2013/01/05 13:10 】 | C/C++ | 有り難いご意見(0)
構造化プログラミング
私が思う構造化プログラミングとは、順次・選択・繰り返しにおいて
状態遷移がきちんと定義されていること。

これを理解できてないプログラマは多いと思う。

ある特定の条件の時だけ値を返すマイルールを
コメントに書かないで平気だとほんと困る。

●非構造化プログラミング

int a = 0; /* condition 1:真 2:偽 */
int b = 0; /* 1:処理Bを実施する 2:処理Bを実施しない */

if(condition)
{
a = 1;
b = 1;
}
else
{
a = 2;
}

if(a==1)
{
if(b==1)
{
/* 処理B */
}
}


●構造化プログラミング

int a = 0; /* condition 1:真 2:偽 */
int b = 0; /* (a = 1のとき)1:処理Bを実施する 2:処理Bを実施しない (左記以外)未定 */

if(condition)
{
a = 1;
b = 1;
}
else
{
a = 2;
}

if(a==1)
{
if(b==1)
{
/* 処理B */
}
}

拍手[0回]

【2012/10/12 06:22 】 | C/C++ | 有り難いご意見(0)
CにもVMあったんだ~

Clang&gcc&LLVM


結局のところ平行四辺形かまるっとした四角形かの違いになるのかな。
アップルが嫌った時のgccも今はやり方が変わっているし
今のコンパイラならもう少し違っていたかもしれない。

Perl5とPerl6くらい違うイメージかな。

個人的にはSSAとCPSとの再会ってすごくおもしろいと思う。

Clangとgccも再会することは・・
ライセンスの壁は厚いし無理か(笑

拍手[0回]

【2012/03/26 07:11 】 | C/C++ | 有り難いご意見(1)
前ページ | ホーム | 次ページ

忍者ブログ [PR]