ラベル cplusplus の投稿を表示しています。 すべての投稿を表示
ラベル cplusplus の投稿を表示しています。 すべての投稿を表示

2009/10/01

[memo] malloc, free(3)

http://www.linux.or.jp/JM/html/LDP_man-pages/man3/malloc.3.html

考えてみれば当たり前なんだけど、free(3) に渡すポインタは malloc(3) 等から返ってきたポインタ「そのもの」でなければならない。以下のコードは FreeBSD 6.4 Release だと実行時に「warning: modified (chunk-) pointer」という警告が出る。Linuxだとアボートする。



バッファに構造体の中身をコピーするようなコードを書いているときに、上記のような間違いを犯したことがあるので記録しておく。

2009/08/21

if statement without bracket

C言語で書かれた以下のコードは合法だし動くんだけど、正直やめてほしい。わかるんだけど気持ち悪くてしょうがない。好みの問題かしら、、(汗

こんなコードが某デスクトップの某巨大ライブラリには浴びるほどあるわけです。全体的な傾向としてはわかりやすいし好きなコードなんだけど、上記だけは僕的にいただけないです。

2009/08/12

[memo] thread safe and portable random function?

スレッドセーフで移植性が高いrandom関数って書けないかしらん。と少し悩んで以下のように書いた。


型の問題を差し引いたとしても、残念なことに上記は移植性がない。関数 [d|s]rand48_r が GNU による拡張だからである。うまい方法を御存知の方がいらっしゃったら教えてくださいませ(´ー`; )

[ Update August 13th 0:03 JST by m ]

pascal君から指摘があったので全面的に書き直しました。古いバージョンは一度だけ呼ぶべき srand48_r関数 を毎回呼んでいました。指摘さんくすです。

2009/05/25

undefined reference(3)

もうこのネタやめにしたいんだけど、一応メモしておく。なんでクラス名忘れるかね。これはひどいとしか言いようがない。原因がわかるまでにかかった時間は2分くらい。

---- test.h ----
#ifndef __TEST_H__
#define __TEST_H__

class A {
public:
static void hoge();
};

#endif // end of __TEST_H__

---- test.cpp ----

#include "test.h"

void hoge() {
return;
}

---- main.cpp ----

#include "test.h"

int main(int argc, char* argv[])
{
A::hoge();
return 0;
}

以下の実行結果は最早おなじみである。

$ g++ main.cpp test.cpp
/tmp/ccSUS3Oq.o: In function `main':
main.cpp:(.text+0x12): undefined reference to `A::hoge()'
collect2: ld はステータス 1 で終了しました

2009/05/21

undefined reference(2)

前のエントリで書き忘れていたので追記しておく。メソッドの実装忘れも俺的にはよくある。たとえば以下のようなコードである。宣言して満足しちゃった、的なアレである。

--- test.cpp ---

#include <iostream>

class A {

public:
// default constructor.
// not implemented.
A();

void helloworld()
{
std::cout << "Hello World!" << std::endl;
}
};

int main(int argc, char *argv[])
{
A a;
a.helloworld();
}

上記をコンパイルすると、下記のようになる。実装がないので、リンカから見えない。以下の結果は当然の帰結である。

$ g++ test.cpp
/tmp/ccIVHTVA.o: In function `main':
a.cpp:(.text+0x74): undefined reference to `A::A()'
collect2: ld はステータス 1 で終了しました

2009/05/20

C++ namespace -> undefined reference to 'main'

C++ の namespace は重要なキーワードであるが、うっかり main 関数のようなグローバルな関数をそれで囲んでしまうと大変なことになる。マングリングによってラベルが変化し、自分が意図した通りにリンカから見えなくなるからである。

namespace はスコープを変えるんだというごく当たり前のことがことがわかっていればこんなことは多分普通やらないんだと思います。多分。ただ、そういう理屈もわかっていない初心者とか、以下のような多段 namespace のマクロを全ファイルに適用するのが癖になっている人とかは要注意である。

--- test.h ---

#ifndef __TEST_H__

#define __MUMUMU_NAMESPACE_NAME__ mumumu
#define __AHO_NAMESPACE_NAME__ aho

//
// namespace macro
//
#define __HOGE_NAMESPACE_START__ \
namespace __MUMUMU_NAMESPACE_NAME__ { \
namespace __AHO_NAMESPACE_NAME__ {
#define __HOGE_NAMESPACE_END__ } }

#endif // end of __TEST_H__

--- test.cpp ---

#include "test.h"

__HOGE_NAMESPACE_START__

int main(int argc, char *argv[]) {
return 0;
}

__HOGE_NAMESPACE_END__

上記の test.cpp をコンパイルすると、以下のようになる。

$ g++ test.cpp
/usr/lib/gcc/i486-linux-gnu/4.3.3/../../../../lib/crt1.o: In function `_start':
/build/buildd/glibc-2.9/csu/../sysdeps/i386/elf/start.S:115: undefined reference
to `main'
collect2: ld はステータス 1 で終了しました

test.cpp を コンパイルし、main の text セクションのみをダンプすると以下のようになる。namespace の情報がラベルに付加されていることがわかる。

$ g++ -c test.cpp
$ objdump -x test.o | grep main
00000000 g F .text 0000000a _ZN6mumumu3aho4mainEiPPc

2008/08/20

m9(*´〜`) (C language memo)

http://d.hatena.ne.jp/keyword/m9%A1%CA%A1%B0%A7%A5%A1%B0%A1%CB%A5%D7%A5%AE%A5%E3%A1%BC%A1%BC%A1%BC%A5%C3

最近俺的にプギャーな出来事が多い。C言語に関して。
  1. static *char func() {} ってナニ!?
  2. 「変数はブロックの初めに宣言しなければならない」というANSI(C89) なルールを巡って「gccなんてゆとりコンパイラ使ってるからだ」といわれのないDISをくらう
  3. 以前 /.J で書いた このコードがセグる 理由を思い出すのに3分かかった
俺は何も学んでいないのかと唖然とするばかり。書きまくるしかないんだよね(´ー`; )

----

Cが体に染み付いている人には釈迦に説法でしかないが、自分へのメモとして上記を解説しておく。

※ 1. は当然 *char なんて型はないのでエラーになる(char* はあるけどね!)。関数の引数や変数宣言については絶対に間違わないのだが、関数の戻り値については上記のような間違いを未だによくする(´ー`; )
※ 2. は gcc4 が C99 なモードでデフォルトは動くから、 int a; a = 1; int b = 100; などというコードをブロックのはじめに書いていても通るのであって、gccが悪いわけではない。こうしたC++的なコードについて、ANSI C 的な警告を出させたければ、-Wall では駄目で、-pedantic オプションをつけてコンパイルする必要がある。
※ 3. は *p == "\n" が、ポインタと文字列の先頭アドレスを比較しているだけであって、実際に文字列比較を行っていないために、無限ループがbreakせず、(たまたま連続して格納されていると思われる) char *envp[] および、それ以降の領域を読んでしまってセグるというもの