May 2008

May 15, 2008

[自分メモ]C言語-動的配列確保?

gccでは配列の要素数を変数で指定することができます。
すごく簡単な例として
int main(int argc, char **argv){
  char darray[atoi(argv[1])];
  return 0;
}
みたいなコードが書けます。

ローカル変数ならばメモリの解放漏れの心配も無いし、これってすごく便利なのでは?と思ったのですが、そこは孔明の罠。

手元のマシンで実験してみたところ、要素数が多すぎてスタック領域の確保に失敗した時に問答無用でSegmentation faultになってしまいます。

スタック領域からメモリを確保する関数でallocaというのもあるのですが、こちらも同様の問題を抱えているようです。

matssaku at 06:19|PermalinkComments(0)TrackBack(0)clip!C 

May 14, 2008

[自分メモ]C言語でリストとかハッシュとか

JavaやPythonなど、豊富なライブラリを持った言語を普段使っていると、C言語で開発するのがとても不便に感じられます。文字列処理の仕組みが貧弱であることに加えて、ListやHashtableなど、便利なデータ型が用意されていないからです。腕に自信がある方であれば自分で実装するのも良いと思いますが、私のようなヘタれプログラマにとっては、品質、パフォーマンス、工数などを考慮すると、やはり実績のあるライブラリが欲しくなります。

そんな時に便利なオープンソースのライブラリを2つ紹介します。

まずはGnome/GTKで利用されているGLibです。GUI向けの仕組みだけでなく、ListやHashtableなど便利なデータ構造、さらには文字列、日付、XMLをあつかうモジュールなど様々なユーティリティが提供されていて汎用的に使うことができます。

もうひとつはapache Webサーバプロジェクトで使われているApache Portable Runtime (APR) です。こちらもApacheとは独立して使うことができます。GLibに比べると小規模でドキュメントも少ないですが、メモリの確保、解放をメモリプールでまとめて管理できるという仕組みがあります。普通のC言語ではmalloc等で確保したメモリは、ポインタを1つ1つ覚えておいて確実に解放する必要がありますが、aprではメモリが欲しいときはあらかじめ作成したメモリプールから切り出し、解放はメモリプールの単位でまとめて行う、という手順になるため、メモリの管理が少し楽になります。(さらにいうとApacheモジュールの中で使う場合はメモリプールの作成、解放をApache自身が行ってくれるため、プログラマはメモリの解放漏れを一切気にする必要が無くなります。)

matssaku at 00:33|PermalinkComments(0)TrackBack(0)clip!C 

May 13, 2008

[自分メモ]autoconf automake

まだ勉強中です。

C言語プログラムのビルドには多くの場合makeを使います。
makeはMakefileに記述されたルールを元に行われます。

ただ、C言語プログラムには依存関係が付き物です。
この依存関係を解決してくれるのがconfigureスクリプトです。
configureスクリプトはMakefile.inという雛型ファイルをもとに依存関係を考慮したMakefileを作ってくれます。

configureスクリプトを生成してくれるツールも存在します。
autoconfはconfigure.acという設定ファイルを元にconfigureスクリプトを生成してくれます。

configure.acファイルのサンプルを作ってくれるコマンドも存在します。
autoscanというコマンドです。

Makefileの雛型、Makefile.inを生成してくれるツールも存在します。
automakeはMakefile.amという、より簡単な設定ファイルを元にMakefile.inを生成してくれます。

うー、ややこしいなぁ。

解りやすい資料を見つけたので追記
http://www.lrde.epita.fr/~adl/dl/autotools.pdf

matssaku at 23:05|PermalinkComments(0)TrackBack(0)clip!C 

May 12, 2008

[自分メモ]log4c

Javaプログラマであればロギングにlog4jを利用している人も多いのではないでしょうか。ログレベル、ログの出力先、ログのフォーマット、といった項目を設定ファイルで切り替えられるのは便利です。

で、C言語でプログラミングする時に同じような便利なライブラリが無いかな、と調べた結果見つけたのがlog4cです。こちらはapacheとは関係が無いようです。

早速使ってみようと思ったのですが、Web上では資料が全くといっていいほど見つかりません。

一応、なんとなく使いかたが分かったのでメモしておきます。

1. インストール
ソースコードをダウンロードし、解凍後、configure→make→make installでインストールできます。デフォルトのインストール先は/usr/local/の下です。コンパイル時のリンカオプションで-llog4cを指定することになります。

2. 設定ファイル
ロギングの設定を記述した設定ファイルを用意する必要があります。ファイルは、
* ${LOG4C_RCPATH}/log4crc
* ${HOME}/.log4crc
* ./log4crc
のいずれかに置きます。
まずは設定例から
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE log4c SYSTEM "">

<log4c version="1.2.1">
 <config>
  <bufsize>0</bufsize>
  <nocleanup>0</nocleanup>
 </config>
 <rollingpolicy name="rp" type="sizewin" maxsize="1024" maxnum="4"/>
 <appender name="ap" type="rollingfile" logdir="/var/log/sample/" prefix="sample.log" layout="dated" rollingpolicy="rp"/>
 <category name="sample" priority="TRACE", appender="ap"/>
</log4c>


rollingpolicyタグにはログファイルのローテーションポリシーを記述します。各属性の意味は以下の通り。
・name 識別子。他のタグ属性から参照される。
・type ローテーションのタイプ。"sizewin"はファイルサイズによる切り替え。
・maxsize ログファイルのサイズがここで設定した値を越えた場合ファイルが切り替えられる。
・maxnum 保存されるログファイルの世代数。

appenderタグにはログの出力先や出力形式を記述します。各属性の意味は以下の通り。
・name 識別子。他のタグ属性から参照される。
・type ログの出力先。"rollingfile"はファイルに出力し、ローテーションが行われる。
・logdir ログを出力するディレクトリのパス。
・prefix ログファイルのファイル名に付けられるプレフィックス。
・layout ログのフォーマット
・rollingpolicy ログファイルのローテーションポリシー。rollingpolicyタグのname属性の値を指定する。

categoryタグにはプログラム内から参照される情報を記述します。各属性の意味は以下の通り。
・name 識別子。プログラム内から参照される。
・priority ログの優先度。プログラム内から参照される。
・appender appenderタグのname属性の値を指定する。

3. ソースコード
log4cを用いたロギングを行うソースコードの例は以下の通り。
#include <stdio.h>
#include "log4c.h"

int main(int argc, char **argv){
 log4c_category_t *lc;
 log4c_init();
 lc = log4c_category_get("sample");
 if(log4c_category_is_priority_enabled(lc, LOG4C_PRIORITY_TRACE)){
  log4c_category_log(lc, LOG4C_PRIORITY_TRACE,
  "this is trace %s:%d",__FILE__,__LINE__);
 }
 if(log4c_category_is_priority_enabled(lc, LOG4C_PRIORITY_DEBUG)){
  log4c_category_log(lc, LOG4C_PRIORITY_DEBUG,
  "this is debug %s:%d",__FILE__,__LINE__);
 }
 if(log4c_category_is_priority_enabled(lc, LOG4C_PRIORITY_INFO)){
  log4c_category_log(lc, LOG4C_PRIORITY_INFO,
  "this is info %s:%d",__FILE__,__LINE__);
 }
 if(log4c_category_is_priority_enabled(lc, LOG4C_PRIORITY_ERROR)){
  log4c_category_log(lc, LOG4C_PRIORITY_ERROR,
"this is error %s:%d",__FILE__,__LINE__);
 }
 log4c_fini();
return 0;
}

この例ではログを出力するかどうかを
log4c_category_is_priority_enabled
関数で判定しています。この関数は設定ファイルのpriority属性を参照し、第2引数で指定したpriorityが設定ファイルと同じか設定ファイルよりも優先度が高い場合に1を返します。

さらに詳しい使い方が知りたい場合はlog4c本体のパッケージに含まれるexamplesが参考になります。

最後に、冒頭でも触れたようにこのライブラリは仕様例や使い方を解説したサイトがすごく少ないです。あまり使われていないようで、バグやパフォーマンス面での不具合があるかもしれません。実際に使う場合にはプリプロセッサで消去できるようにしておいた方が無難です。

matssaku at 23:03|PermalinkComments(0)TrackBack(0)clip!C