メモリプールを使ってみる
APR(Apache Portable Runtime)のメモリプール機能を使ってみました。メモリプールを利用して、メモリを確保する流れは次のようになるようです。
- apr_pool_create関数を使用して、メモリプールを作成します。
- apr_pallocまたはapr_pcalloc関数を使用して、メモリプールからメモリを確保します。
- 確保したメモリを使用します。
- apr_pool_clearまたはapr_pool_destroy関数を使用して、メモリプールを破棄します。
上記でメモリの解放という手順は存在しません。APRではメモリプールの単位でメモリを管理していて、メモリ解放は適宜実施してくれるようです。
上記では、メモリプールを1つしか作らない流れですが、メモリプールは複数作成する事が可能で、各メモリプールは、親子関係を付ける事が出来ます。
プログラム例
親子関係のメモリプールを作成し、メモリ確保し、確保したメモリに文字列を書き込むプログラムを作成してみました。
try_apr_pools.c
/* * APRのメモリプール機能を使ってみました。 */ #include <stdio.h> #include "apr_pools.h" int main(int argc, char **argv) { apr_status_t status = APR_SUCCESS; apr_pool_t *pool = NULL; apr_pool_t *pool2 = NULL; void *ptr = NULL; // APRを初期化する。 apr_initialize(); // 親プールを作成する。 status = apr_pool_create(&pool, NULL); if (status == APR_SUCCESS) { // メモリを確保する。 ptr = apr_pcalloc(pool, 10); // 子供プールを作成する。 status = apr_pool_create(&pool2, pool); if (status == APR_SUCCESS) { // メモリを確保する。 ptr = apr_pcalloc(pool2, 10); if (ptr != NULL) { // 書き込み strcpy((char*)ptr, "Hello"); printf("書き込み結果 [%s]\n", ptr); } // メモリを解放する。 apr_pool_clear(pool2); } else { printf("子供プールを作成できませんでした。\n"); } // プールを破棄する。 apr_pool_destroy(pool); } else { printf("親プールを作成できませんでした。\n"); } // APRを終了する。 apr_terminate(); return 0; }
実行結果
$ ./try_apr_pools.exe
書き込み結果 [Hello]
補足
参考サイト
Memory Pool Functions
http://apr.apache.org/docs/apr/1.2/group__apr__pools.html
動作環境
OS : Windows XP, Cygwin
APR Version : 1.2.12
ハッシュテーブルを使ってみる
APR(Apache Portable Runtime)のハッシュ機能を使ってみました。ハッシュ機能を利用する場合の手順は次のようになるようです。
- apr_pool_create関数を使用して、ハッシュ機能で使用するメモリプールを作成します。
- apr_hash_make関数を使用して、ハッシュテーブルを作成します。
- apr_hash_set関数を使用して、ハッシュテーブルに要素を追加します。
- apr_hash_set,apr_hash_get,apr_hash_first,apr_hash_next,apr_hash_this,apr_hash_count関数などを使用して、各要素にアクセスします。
- ハッシュテーブルを使い終わったら、apr_pool_clearまたはapr_pool_destroy関数を使用して、メモリプールを破棄します。
プログラム例
ハッシュテーブルへ、文字列のキーと値のペアを3つ登録し、各要素の取得、変更、削除をするサンプルプログラムを作成してみました。
try_apr_hash.c
#include <stdio.h> #include "apr_hash.h" void print_hash(apr_pool_t *pool, apr_hash_t *hash) { apr_hash_index_t *hash_index = NULL; const void *key = NULL; void *val = NULL; // 要素数を出力する。 printf("要素数:[%d]\n", apr_hash_count(hash)); // 内容を出力する。 hash_index = apr_hash_first(pool, hash); while (hash_index) { apr_hash_this(hash_index, &key, NULL, &val); printf("key=[%s], value=[%s]\n", (char*)key, (char*)val); hash_index = apr_hash_next(hash_index); } } int main(int argc, char **argv) { apr_status_t status = APR_SUCCESS; apr_pool_t *pool = NULL; apr_hash_t *hash = NULL; char *key1 = "key1"; char *key2 = "key2"; char *key3 = "key3"; char *value1 = "value1"; char *value2 = "value2"; char *value3 = "value3"; char *value4 = "value4"; // APRを初期化する。 apr_initialize(); // メモリプールを作成する。 status = apr_pool_create(&pool, NULL); if (status == APR_SUCCESS) { // ハッシュを作成する。 hash = apr_hash_make(pool); // 要素を追加する。 apr_hash_set(hash, key1, APR_HASH_KEY_STRING, value1); apr_hash_set(hash, key2, APR_HASH_KEY_STRING, value2); apr_hash_set(hash, key3, APR_HASH_KEY_STRING, value3); printf("キー[%s]の値=[%s]\n", key1, (char*)apr_hash_get(hash, key1, APR_HASH_KEY_STRING)); // ハッシュの内容を出力する。 print_hash(pool, hash); // 要素を変更する。 apr_hash_set(hash, key2, APR_HASH_KEY_STRING, value4); // ハッシュの内容を出力する。 print_hash(pool, hash); // 要素を削除する。 apr_hash_set(hash, key2, APR_HASH_KEY_STRING, NULL); // ハッシュの内容を出力する。 print_hash(pool, hash); } else { printf("メモリプールを作成できませんでした。\n"); } // APRを終了する。 apr_terminate(); return 0; }
実行結果
$ ./try_apr_hash.exe
キー[key1]の値=[value1]
要素数:[3]
key=[key1], value=[value1]
key=[key2], value=[value2]
key=[key3], value=[value3]
要素数:[3]
key=[key1], value=[value1]
key=[key2], value=[value4]
key=[key3], value=[value3]
要素数:[2]
key=[key1], value=[value1]
key=[key3], value=[value3]
補足
apr_hash_set関数について
引数にキーと値のポインタを渡します。ハッシュテーブルの各要素は、ポインタで参照される領域をそのまま使用するようです。そのため、呼び出し側で用意したキーと値の領域は、ハッシュテーブルを使い終わるまで、保持しておく必要があるようです。
参考サイト
Apache Portable Runtime: Hash Tables
http://apr.apache.org/docs/apr/1.2/group__apr__hash.html
動作環境
OS : Windows XP, Cygwin
APR Version : 1.2.12
Array機能を使ってみる
APR(Apache Portable Runtime)のArray機能で動的配列を使ってみました。Array機能を利用する場合の手順は次のようになるようです。
- apr_pool_create関数を使用して、Array機能で使用するメモリプールを作成します。
- apr_array_make関数を使用して、apr_array_header_tを作成します。
- apr_array_push関数を使用して、要素を追加します。
- apr_is_empty_array, apr_array_push, apr_array_pop関数など、またapr_array_header_t構造体の各要素を使用して、配列の各要素にアクセスします。
- apr_array_headerを使い終わったら、apr_pool_clearまたはapr_pool_destroy関数を使用して、メモリプールを破棄します。
プログラム例
try_apr_array.c
/* * APR Array機能 * 新規作成:2008/01/14 */ #include <stdio.h> #include "apr_tables.h" void print_array(apr_array_header_t *arr) { int i = 0; int *val_ptr = NULL; if (apr_is_empty_array(arr)) { printf("要素はありません。\n"); } else { // Arrayの内容を出力する。 for (i = 0; i < arr->nelts; i++) { val_ptr = (int*)(arr->elts + (arr->elt_size * i)); printf("要素[%d]の値:[%d]\n", i, *val_ptr); } } } int main(int argc, char **argv) { apr_status_t status = APR_SUCCESS; apr_pool_t *pool = NULL; apr_array_header_t *arr = NULL; int *val_ptr = NULL; // APRを初期化する。 apr_initialize(); // メモリプールを作成する。 status = apr_pool_create(&pool, NULL); if (status == APR_SUCCESS) { // int型要素のArrayを作成する。 arr = apr_array_make(pool, 0, sizeof(int)); // 要素を追加する。 val_ptr = apr_array_push(arr); *val_ptr = 10; val_ptr = apr_array_push(arr); *val_ptr = 20; val_ptr = apr_array_push(arr); *val_ptr = 30; // Arrayの内容を出力する。 print_array(arr); // 2番目の要素を変更する。 val_ptr = (int*)(arr->elts + (arr->elt_size * 1)); *val_ptr = 21; // Arrayの内容を出力する。 print_array(arr); // 要素を削除する。 apr_array_pop(arr); // Arrayの内容を出力する。 print_array(arr); // メモリプールを破棄します。 apr_pool_destroy(pool); } else { printf("メモリプールを作成できませんでした。\n"); } // APRを終了する。 apr_terminate(); return 0; }
実行結果
$ ./try_apr_array.exe
要素[0]の値:[10]
要素[1]の値:[20]
要素[2]の値:[30]
要素[0]の値:[10]
要素[1]の値:[21]
要素[2]の値:[30]
要素[0]の値:[10]
要素[1]の値:[21]
補足
参考サイト
Apache Portable Runtime: Table and Array Functions
http://apr.apache.org/docs/apr/1.2/group__apr__tables.html
井上の日誌 -Apacheの話-(2006-03-30)
https://www.codeblog.org/blog/inoue/20060330.html
動作環境
OS : Windows XP, Cygwin
APR Version : 1.2.12
Table機能を使ってみる
APR(Apache Portable Runtime)のTable機能を使ってみました。Table機能を利用する場合の手順は次のようになるようです。
- apr_pool_create関数を使用して、Table機能で使用するメモリプールを作成します。
- apr_table_make関数を使用して、apr_table_tを作成します。
- 次の関数を使用して、要素を操作します。
- apr_table_tを使い終わったら、apr_pool_clearまたはapr_pool_destroy関数を使用して、メモリプールを破棄します。
主要な要素操作の関数
関数 | 概要 |
---|---|
apr_table_add | 要素を追加します。キーが重複しても場合、異なる要素として追加します。キーと値は内部的にコピーされます。 |
apr_table_addn | apr_table_addと同様ですが、キーと値は内部的にコピーされません。 |
apr_table_clear | 全要素を削除します。 |
apr_table_get | 指定されたキーに一致する要素を取得します。 |
apr_table_set | 要素を登録します。キーが重複する場合、上書きになります。キーと値は内部的にコピーされます。 |
apr_table_setn | apr_table_setと同様ですが、キーと値は内部的にコピーされません。 |
apr_table_unset | 要素を1つ削除します。 |
apr_table_elts | 全要素(apr_table_entry_t)の配列(apr_array_header_t)を取得します。 |
プログラム例
try_apr_table.c
/* * APR Table機能 * 新規作成:2008/01/14 */ #include <stdio.h> #include "apr_tables.h" void print_table(apr_table_t *table) { if (apr_is_empty_table(table)) { printf("要素はありません。\n"); } else { const apr_array_header_t *arr = apr_table_elts(table); int i; for (i = 0; i < arr->nelts; i++) { apr_table_entry_t *entry = (apr_table_entry_t *)(arr->elts + (arr->elt_size * i)); printf("%d番目の要素:キー=[%s],値=[%s]\n", i, entry->key, entry->val); } } } int main(int argc, char **argv) { char key1[] = "key1"; char key2[] = "key2"; char key3[] = "key3"; char val1[] = "value1"; char val2[] = "value2"; char val3[] = "value3"; // APRを初期化する。 apr_initialize(); // メモリプールを作成する。 apr_pool_t *pool = NULL; apr_status_t status = apr_pool_create(&pool, NULL); if (status == APR_SUCCESS) { // ------------------------------ // Tableの作成 // ------------------------------ // Tableを作成する。 // 初期領域サイズは、要素5個分とした。 apr_table_t *table = apr_table_make(pool, 5); // 要素を登録する。 apr_table_set(table, key1, val1); apr_table_set(table, key2, val2); apr_table_set(table, key3, val3); // 内容を出力する。 print_table(table); // ------------------------------ // 要素の変更 // ------------------------------ printf("変更前:[%s]\n", apr_table_get(table, key2)); apr_table_set(table, key2, "Hello"); printf("変更後:[%s]\n", apr_table_get(table, key2)); // ------------------------------ // 要素の削除 // ------------------------------ printf("要素の削除\n"); apr_table_unset(table, key2); print_table(table); // ------------------------------ // 全要素のクリア // ------------------------------ printf("要素のクリア\n"); apr_table_clear(table); print_table(table); // メモリプールを破棄します。 apr_pool_destroy(pool); } else { printf("メモリプールを作成できませんでした。\n"); } // APRを終了する。 apr_terminate(); return 0; }
実行結果
$ ./try_apr_table.exe
0番目の要素:キー=[key1],値=[value1]
1番目の要素:キー=[key2],値=[value2]
2番目の要素:キー=[key3],値=[value3]
変更前:[value2]
変更後:[Hello]
要素の削除
0番目の要素:キー=[key1],値=[value1]
1番目の要素:キー=[key3],値=[value3]
要素のクリア
要素はありません。
補足
参考サイト
Apache Portable Runtime: Table and Array Functions
http://apr.apache.org/docs/apr/1.2/group__apr__tables.html
井上の日誌 -Apacheの話-(2006-04-05)
https://www.codeblog.org/blog/inoue/20060405.html
動作環境
OS : Windows XP, Cygwin
APR Version : 1.2.12
Windowsのエディタを起動する関数
Cygwinのコマンドライン上から、普段使いなれたWindows用エディタを起動したくなりました。
私が愛用しているエディタは、「サクラエディタ」ですが、このエディタをCygwin上からコマンド実行で起動する関数を作成しました。下記のようになります。
この関数を~/.bashrcに記述して使う事で、ちょっと便利になりました!
# サクラエディタ起動 関数 # 2008/01/14 alias _sakura="/cygdrive/c/Program\ Files/sakura/sakura.exe" function sakura() { if [[ "$#" == "0" ]] then _sakura & else for path in $* do ( _sakura `cygpath -aw $path` & ) done fi }