ポインタでも結構ですから御教授頂ければ幸いです。
問題:
構造体の配列に割り当てられたメモリ領域の全てのバイトを0で初期化する
ルーチンがあります。
ルーチン単体のテストでは割り当て/読み書き共全く問題なく動作するのに、
他のルーチンと結合した後、メモリ領域を割り当てて、(割り当ては成功
しているように見える)書き込もうとするとSegmentation faultを起こします。
システムはTurboLinux4.2で、libcなどは変更していません。
Segmentation faultを起こした時、perror()はSuccessを表示し、返される
メモリもNULLではありません。
ソフトが起動してから最初に行なわれるmalloc/callocなので、原因の特定に
苦しんでいます。
思い当たる点といえば、他のファイル中でstatic constな変数を多用している
とか、(恐らく合計は100KB未満でしょう。なお、大きな配列はmallocで確保
するようにしています)pthreadライブラリをリンクしている位です。
(ただしpthread関連の操作は該当ルーチンを呼び出した後で行なわれます)
なお、あまり参考にはならないと思いますが、ソフトを構成するソースファイル
の
合計は100KB程度です。そのうちstatic constな定数を設定しているヘッダファ
イルの合計は39KB程度です。
Apacheのソースを検索するとsbrkを使ってデータ領域を拡張しているようです
が、
メモリ使用量も大きくなると、これらの使用を検討すべきなのでしょうか。
#もしくはヒープ領域を拡張するとか?
もっとも、何時どの様にsbrk/brkを使うのかを理解しておりませんが…。
ソースの抜粋を以下に書いておきます。重ねて言いますが、単体では問題なく
動作します。
**********************ソースから抜粋****************************
typedef struct {
int mimenum;
int length;
char mimetype[64];
char extension[8];
int count;
} _MIMETYPE; /* Total 84 Bytes */
static _MIMETYPE *_mimetypes;
main(){
....
/* この時点で
getrlimitによるmallocあるいはcalloc直前の情報
RLIMIT_STACK rlim_cur: 8388608, rlime_max: 2147483647
RLIMIT_MEMORY rlim_cur: 2147483647, rlime_max: 2147483647
*/
_mimetypes = (_MIMETYPE *)calloc(sizeof(_MIMETYPE), 512); /* 84 * 512
= 43008Bytes */
if (_mimetypes == NULL){
exit(-1); /* 何故か割り当ては成功している。失敗はしたことがない */
}
perror("memory allocate :");
mimetypes_load();
...
}
/* 0バイト目の初期化で失敗する模様 */
void mimetypes_load(){
int i;
char *tmp;
/* この時点で _mimetypes は 0x805a860(例) を指している */
memset((void*)_mimetypes, 0, sizeof(_MIMETYPE)* 512); /* 単体ではOK */
あるいは
tmp = (char *)_mimetypes;
for(i = 0; i < sizeof(_MIMETYPE)*512; i++){
tmp[i] = 0; /* i = 0でSIGSEGVを起こす。単体のテストでは問題なし */
}
またあるいは、正攻法で
for(i = 0; i < 512; i++){
_mimetypes[i].mimenum = 0; /* i = 0で失敗する。単体のテストでは問題
なし */
_mimetypes[i].length = 0;
_mimetypes[i].extension[0] = 0;
_mimetypes[i].count = 0;
}
}
>Segmentation faultを起こした時
正しくは
Segmentation faultを起こす前
です。
メモリに値を書き込む直前に行ったメモリのmalloc/callocは問題
なかった、ということです。
In article <38A75FEE...@mail.goo.ne.jp> ,
歩野零一<_teku...@mail.goo.ne.jp> writes
>static _MIMETYPE *_mimetypes;
なんで_を使うのかな? もしかして、これを、複数のファイルに書いてませんか?
そうすると、それはファイルごとに独立な変数になります。片方を初期化しても
もう一方は初期化されてません。
別に、このプログラム自体はちゃんと動くみたいですけど。複数の
ファイルにわけるとだめなんですよね?
---
Shinji KONO @ Information Engineering, University of the Ryukyus
河野真治 @ 琉球大学工学部情報工学科
Shinji Kono wrote:
> なんで_を使うのかな? もしかして、これを、複数のファイルに書いてませんか?
> そうすると、それはファイルごとに独立な変数になります。片方を初期化しても
> もう一方は初期化されてません。
私も最初はそう疑いました.
この構造体とstatic なポインタは一つのヘッダファイルでのみ宣言
されています。もちろん、grepでチェック済みです。
> 別に、このプログラム自体はちゃんと動くみたいですけど。複数の
> ファイルにわけるとだめなんですよね?
分けるというか、最初から分かれています。
テストとは、このルーチンのあるファイル(hogehoge.c)に、
#ifdef HOGEHOGE_TEST
main()
{
int i;
_mimetypes = (_MIMETYPES *)malloc(....);
mimetypes_load();
....中略....
for (i = 0; i < 512; i++){
printf("mimetypes %s\n", _mimetypes[i].xxxx);
}
}
#endif
のような仕掛けをしておいて、cc hogehoge.c -DHOGEHOGE_TESTとやって
出力を確認しています。
ヘッダが1つでもソースが別ならstatic変数は別の変数になりますが
その点は大丈夫ですか?
--
// 沖野 幸治 OKINO Kouji
// 株式会社コア 北海道カンパニー
// E-mail: ok...@core.co.jp
OKINO Kouji wrote:
> ヘッダが1つでもソースが別ならstatic変数は別の変数になりますが
> その点は大丈夫ですか?
ちなみにコンパイルはすべて一つのコマンドラインで行っています。
cc mainloop.c token.c .... -DMAINLOOP_TEST -lpthread
mainloop.cにmain()があって、mallocを行っています。
ソースファイルが2つ以上あって、それぞれで同じ名前でstatic変数を
宣言しても、別々の変数として扱われるという話で、コンパイルする時に
コマンドラインが1つかどうかとは関係ない話ですが?
> cc mainloop.c token.c .... -DMAINLOOP_TEST -lpthread
> mainloop.cにmain()があって、mallocを行っています。
で、書き込みはどのソースファイルでやってるんですか?
mainloop.c以外でやるのなら、staticにしちゃ駄目です。
歩野零一さん、こんにちは。
> > ヘッダが1つでもソースが別ならstatic変数は別の変数になりますが
> > その点は大丈夫ですか?
>
> ちなみにコンパイルはすべて一つのコマンドラインで行っています。
> cc mainloop.c token.c .... -DMAINLOOP_TEST -lpthread
> mainloop.cにmain()があって、mallocを行っています。
答えになっていませんよ(^_^;)。 コンパイルを一つのコマンドラインで行って
も複数で行ってもオプションが同一なら答えは同じです。static変数を含むファイル
を複数のcファイルでincludeしていないか聞かれているのです(^○^)。
In article <38A77754...@mail.goo.ne.jp> 歩野零一 <_teku...@mail.goo.ne.jp> writes:
> なんだか凡ミスを繰り返している気がしてきました。
> OKINO Kouji wrote:
>
>> ヘッダが1つでもソースが別ならstatic変数は別の変数になりますが
>> その点は大丈夫ですか?
>
> ちなみにコンパイルはすべて一つのコマンドラインで行っています。
コンパイルの仕方は関係ありませんよ。
> cc mainloop.c token.c .... -DMAINLOOP_TEST -lpthread
> mainloop.cにmain()があって、mallocを行っています。
普通、変数はヘッダで宣言するものではありません。
片方のソース内で宣言して、もう片方ではその変数を extern で
参照するものです。
# ヘッダには extern 宣言を書いておく。
static や extern とか「スコープ」とかそういうキーワードの
意味をちゃんと把握されていますか?
--
-----
Nakano
> > ヘッダが1つでもソースが別ならstatic変数は別の変数になりますが
> > その点は大丈夫ですか?
>
> ちなみにコンパイルはすべて一つのコマンドラインで行っています。
> cc mainloop.c token.c .... -DMAINLOOP_TEST -lpthread
> mainloop.cにmain()があって、mallocを行っています。
>
関係ないかも知れませんが,コンパイル時にフラグ -pthread または
-D_REENTRANT を追加しています?
--
Takeyasu Wakabayashi
Faculty of Economics, Toyama University
twa...@eco.toyama-u.ac.jp
歩野零一 wrote in <38A77754...@mail.goo.ne.jp>
> なんだか凡ミスを繰り返している気がしてきました。
沖野さんのフォローで、だいたいおわかりのような気がしますが
もう少し説明させていただきます。
static の使い方が違うと思うんです。
歩野さん、変数名の頭から、 static を取るとエラーになりませ
んか?逆に言うとエラーになるんで、static つけていませんか?
通常、変数は .c または .cpp ファイルに記述し、その変数を他
のファイルから参照できるように、.h ファイルに
extern _MIMETYPE *_mimetypes;
なんて感じで外部参照として定義します。
他の .c や .cpp ファイルでこのヘッダーファイルをインクルー
ドしてやることによって、_mimetypes は、このファイル内にはな
いけれども、どこか他のファイルにある変数なんだって、コンパイ
ラーは理解して、リンカーに渡す情報を作成します。
=== Nihon Application Co.,LTD. 木屋 善夫 ki...@nac.co.jp ===
皆様の仰るとおり、static宣言が間違いでした。
なんでつけてしまったのかというと多分、threadを使いまくるから、
スタックの消費を抑えたい、という意識が働いたのだと思います。
勉強が不徹底でした。もっともっと精進いたします。
In article <38A78ED5...@mail.goo.ne.jp> ,
歩野零一<_teku...@mail.goo.ne.jp> writes >皆様の仰るとおり、
static宣言が間違いでした。
原因がわかって良かったですね。
僕は、わりと、こんな風に fj を使うのが好きです。他の人の
勉強にもなりますからね。
外部参照として宣言します。の誤り
ではないですか。
とゆうか、グローバル変数は宣言と定義は
ひとつのヘッダにまとめたほうが楽に管理
できます。
参考文献:
Cプログラミング診断室
藤原博文著
技術評論社刊
--
しまもとけんろう
> Cプログラミング診断室
> 藤原博文著
> 技術評論社刊
Web版があります。
http://www.pro.or.jp/~fuji/mybooks/cdiag/cdiag.5.4.html