【日記】dashのコードを紙にプリントアウトして読んでいる

Pocket
LINEで送る

本日はdashのコードの精読を開始しました。査読が3件、査読の割り振りが3件、自分の論文再提出が1件(全部英文だ馬鹿野郎)溜まってますが、シェルに比べたらそんなことは大したことではありません。「シェルは身を滅ぼす」なんて諺もありますし。

続きを読む 【日記】dashのコードを紙にプリントアウトして読んでいる

Pocket
LINEで送る

variable length array で配列の要素数の限界を調べた(しかしvariable length arrayあまり関係ない)

Pocket
LINEで送る

前回の variable length array、なんでそんなに自分が気持ち悪いと感じるのかと考えてみました。結果、WindowsでVisual C++を昔(4.0~6.0あたり)使っていたときに、デフォルトのスタック領域の大きさがそんなに大きくなく、

int aho[100000];

などとすると実行時エラーが起こっていたのが遠因のようです。スタック領域はビビりながら使う物で、variable length array などとんでもないと。

例えば、このページに Windows CEのケースが書いてあります。確か Windows 95, 97 で Visual C++ を使っても全く同じだったと記憶しています。

しかし、もう15年以上も経っているしOSも違うので、自分の感覚は調整しないといけません。実験しましょう。なぜこのクソ忙しいのにそんなことをするのか。それは、今出ている会合がもう休み無しでもうすぐ4時間経過しようとしているからです。息抜きしないと死ぬぞこれ。

まず、自分のマシーンのスタックの大きさを調べます。ulimitというコマンドで調査できます。

uedamac:~ ueda$ ulimit -s
8192
//単位をバイトに直す。
uedamac:~ ueda$ ulimit -s | awk '{print $1*1024}'
8388608

ということで、int型だとだいたい 2百万くらいが配列の要素数の限界と言えそうです。

次に取り出しますのは前回の気持ち悪いコードをちょっと修正したもの。

uedamac:~ ueda$ cat hoge.c
#include <stdio.h>

void kidding_me(size_t size)
{
	int nums[size];//気持ち悪い

	int i;
	for(i=0;i&amp;lt;size;i++){
		nums[i] = i;
		printf("%d\n",nums[i]);
	}
}

int main(int argc, char const* argv[])
{
        int num = atoi(argv[1]);
        printf("%ld\n",num*sizeof(int));
        kidding_me(num);

        return 0;
}

オプションで配列の個数を指定すると、それだけスタックを確保してくれます気持ち悪いですねー。

コンパイルして、とりあえず200万を指定して実行してみます。

uedamac:~ ueda$ gcc ./hoge.c
uedamac:~ ueda$ ./a.out 2000000 | tail -n 1
1999999

甲斐甲斐しく動いています。

じゃあ動かなくなるのはどれくらいなんだ、と。

いろいろ調べた結果、209万6105でSegmentation faultが発生しました。素直な結果でよかったよかった。

uedamac:~ ueda$ ./a.out 2096104 | head
8384416
0
1
2
3
4
5
6
7
8
uedamac:~ ueda$ ./a.out 2096105
8384420
Segmentation fault: 11

ということで、私のMacだと100万レベルでガボッと配列を確保していいようです。これならいいか。

でも、自分で配列の個数の上限をチェックするコードを書く事になるんだから、決まった数の配列を作って、それを使った方がいいんじゃないのかなあ???

うーん。

続く。

Pocket
LINEで送る

C言語(C99)の variable length array というものを初体験

Pocket
LINEで送る

こちらを拝読してびっくりしたので検証しました。

http://cpplover.blogspot.jp/2013/04/llvmclanglinuxgcc.html

variable length array自体は、GCCは大昔から拡張機能としてサポートしている。C99では正式に採用された。

配列のサイズにconstでない変数をぶち込んでも良いとのこと・・・。しかも大昔から。ほんまかい。

こんなコードを書いて・・・

uedamac:~ ueda$ cat hoge.c
#include

void kidding_me(size_t size)
{
	int nums[size];

	for(int i=0;i<size;i++){
		nums[i] = i;
		printf("%d\n",nums[i]);
	}
}

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

こんぴゃーるして実行。-std=c99 というオプションが必要なのか?

uedamac:~ ueda$ gcc ./hoge.c
./hoge.c: In function ‘kidding_me’:
./hoge.c:7: error: ‘for’ loop initial declaration used outside C99 mode
uedamac:~ ueda$ gcc -std=c99 ./hoge.c
uedamac:~ ueda$

あ、サイズが可変なことより、for(int …の方が怒られているのね。もしかしてオプション要らないんじゃないか?

書き直してコンパイル・・・と。

uedamac:~ ueda$ cat hoge.c
#include

void kidding_me(size_t size)
{
	int nums[size];

	int i=0;
	for(i=0;i<size;i++){
		nums[i] = i;
		printf("%d\n",nums[i]);
	}
}

int main(int argc, char const* argv[])
{
	kidding_me(4);
	return 0;
}
uedamac:~ ueda$ gcc ./hoge.c
uedamac:~ ueda$ ./a.out
0
1
2
3

特に技術的にごちゃごちゃ書く元気はありませんが、一言言わせてください。

気持ち悪い!

以上です。これは・・・使わない方がよいと思う・・・。いや、オッサンだからそう思うだけか・・・。ポータビリティーというより、なんかメモリの使い方の前提が分からなくなりそうなので・・・。シェルスクリプトは動けばいいというのが持論なんだけど、Cのコードはちょっと違うのかなと。はたまた自分の頭が固いのか。

これ知ってる人ってどれだけいるんだろ?

Pocket
LINEで送る