- ベストアンサー
HP-UXへの移植でセグメンテーション障害が発生し、困っています
HP-UXへの移植で困っています。 strcpy(Month->Data,Data.arr); というコードがあり、今まではDigital Unix上では正常に動作していました。しかしHP-UX上でコンパイル、実行するとセグメンテーション障害が発生し、正常に動作しません。 どなたか助けてください。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
ひとつ気になった点があります。 #1の補足にあるコードには、MONTH_RECの「定義」がありません。 そして、alloc_Month()では > Month= (MONTH_REC *)malloc(sizeof(struct Month_t)); とかやってますけど、 MONTH_REC と struct Month_t って本当に同じものですか? あと、alloc_Monthの実装も 使ってない変数 int iがある一方で、引数で貰ってきた ものを変数として使いまわしているし ちょっと首を傾げたくなる書き方です。 MONTH_REC* alloc_Month2(MONTH_REC *Month) { /* MONTH_REC *p = (MONTH_REC *)calloc(1, sizeof (struct Month_t)); */ MONTH_REC *p = (MONTH_REC *)calloc(1, sizeof (MONTH_REC)); MONTH_REC *q = Month; if (!p) { Exit(ERROR,__FILE__,__LINE__); } if (!q) { Month_top = p; } else { q->after = p; } Month_end = p; return p; } のような感じに書き換えたらどうなります? #あーqはいらなかったか。 あ、もうひとつ追加。 >alloc_Month()関数はNULLではありませんでしたが、strcpy(Month->Data,(char *)Data.arr); >手前でMonth->Dataをチェックしてみると 「Bad Address」とメッセージが返されてしまいました とありますが、この strcpyの実行直前の Month を %p 書式で出力したときの値と、 これを割り当てた alloc_Monthのなかでの memset(Month,NULL,sizeof(struct Month_t)); の前後での Monthを%p出力したときの値は 全部同じ値になってますか? Month_tの定義では typedef struct Month_t MONTH; struct Month_t{ struct Month_t *after; char Data[8+1]; }; なので、Monthが正しい値である場合に Month->Dataが 変な値(0?)になることはないと思いますが?
その他の回答 (5)
- sakusaker7
- ベストアンサー率62% (800/1280)
64bit環境の場合、0とNULLとのとり違いが致命的になりうる場合があります。 初級C言語Q&A(3) http://www.st.rim.or.jp/~phinloda/cqa/cqa3.html の Q 【関数呼び出しの0】 関数呼び出しの引数としてヌルポインタを書く場合、0と書いてはいけないと言われた。 [その他] BINARY HACKS - COLUN++ BLOG http://d.hatena.ne.jp/colun/20061203 NULLと0は等しい? あたりにその辺に絡んだ話があります。 詳しくは Binary Hacks ―ハッカー秘伝のテクニック100選: 本: 高林 哲,鵜飼 文敏,佐藤 祐介,浜地 慎一郎,首藤 一幸 http://amazon.jp/dp/4873112885 のHACK#49「64ビット環境で0とNULLの違いに気を付ける」 を読んでみてください。 ただ考え直すとmemsetは可変引数をとる関数じゃないし、 プロトタイプ宣言がちゃんとされていればキャストがかかるだろうし、 予測は外してるっぽいのには違いありませんが。 データモデルとは? http://www.oklab.org/language_c/lp64.html
- morimonmon
- ベストアンサー率0% (0/1)
私のコードの読み違いなら申し訳ないのですが、 alloc_Month()関数で、 if(!Month){ Exit(ERROR,__FILE__,__LINE__); } としているため、Month != NULL の場合は必ず Exit してしまいます。 結果、alloc_Month()関数の戻り値は必ず NULL なのではないでしょうか? Month = NULL の場合の memset(Month,NULL,sizeof(struct Month_t)); の動作は試していないのでどうなるのか分かりませんが。。 Month = NULL で戻ってきているため、直後の strcpy(Month->Data,(char *)Data.arr); でセグメンテーションフォルトになります。 Month が NULL になっている原因は分かりませんが、 alloc_Month()関数での malloc() が失敗すると戻り値が NULL となり、 Month に NULL が代入されてしまうこともありえます。 また少し質問とは外れますが、上記 memset() の第2引数が NULL は問題ないと思います。 ほとんどの処理系では、 stdio.h の中で #define NULL 0 と定義されています。HP-UX も同様だと思います。 NULL か 0 か '\0' かは、結局同じ値になるので、 私はコードの視認性を考え、その場に応じた書き方をするようにしています。
- sakusaker7
- ベストアンサー率62% (800/1280)
ここまで状況が絞り込めているのなら、デバッガでステップ実行すれば すぐに場所をピンポイントで特定できそうな気がするんですが、 実は毎回発生するわけじゃなくて何かの拍子にSEGVが起きるとかだったりします? とりあえず共有メモリ領域を他のスレッドやプロセスがぶっ壊しているという 可能性はないとして、 Month= (MONTH_REC *)alloc_Month(Month); strcpy(Month->Data,(char *)Data.arr); ↑このalloc_Monthの呼び出し後に毎回SEGVしているということでいいですか? 一つだけ気になる部分があります。 alloc_Monthの中で >memset(Month,NULL,sizeof(struct Month_t)); というのがありますが、HP-UXって64ビットOSですよね? HP-UXのccがILP64なのかLP64なのか、はたまたLLP64なのかは知りませんが memsetの第二引数に NULL を渡しているのはまずいような気がします。 関数にしようとしては int を期待しているのにポインタを渡しているわけですから。 #もちろんそれで問題ない場合もありますが Digital UNIXでは発生していなかったということですので(たしかこれも 64ビットOSでしたよね?)あんまり自信はありません。 もしなんらかの理由でデバッガでステップ実行を試せないのなら、 alloc_Monthのところどころ(先頭とリターン直前の部分と、memsetの 前後くらいかな)で データがおかしくなっていないかチェックしてみてください。 Data.arrは見るのが大変でしょうが、Monthもぶっ壊れているということですから とりあえずこちらだけでも。
補足
アドバイスありがとうございます。 alloc_Monthの呼び出し後に毎回必ずSEGVしています。 memset(Month,NULL,sizeof(struct Month_t)); がおかしいとは思っていませんでした。NULLの部分を変更して実行してみます。
- asuncion
- ベストアンサー率33% (2127/6290)
構造体のメンバー arr を、どこでどのように定義しているのでしょうか?
補足
ANo.1の方の補足にコードのほうを記述していますので参考頂ければと思います。なお、定義は以下です。 <Month.h> typedef struct Month_t MONTH; struct Month_t{ struct Month_t *after; char Data[8+1]; }; MONTH *Get_Month_top();
- sakusaker7
- ベストアンサー率62% (800/1280)
そのstrcpyでSEGVしているんなら、パラメータの値をチェックしました? 多分移植前のシステムでは正常動作していたってのは勘違いで、 未初期化のポインタを使ってたりしていたのがたまたま動いていただけで HP-UXに持ってきたときにバグが顕在化しただけじゃないですか? つか助けろって言われたってたったそれだけの情報じゃ無理だって。
補足
以下今回のコードです。 <Month.h> typedef struct Month_t MONTH; struct Month_t{ struct Month_t *after; char Data[8+1]; }; MONTH *Get_Month_top(); <Month.c> static MONTH_REC *alloc_Month(); static MONTH_REC *Month_top; static MONTH_REC *Month_end; int Read_Month() { EXEC SQL BEGIN DECLARE SECTION; VARCHAR sqlstmt[4096]; VARCHAR Data[20]; EXEC SQL END DECLARE SECTION; MONTH_REC *Month = NULL; sprintf((char *)sqlstmt.arr, "SELECT\ D.Data\ FROM \ %s D \ WHERE \ TO_CHAR(D.YEARMONTH,'YYYYMM') = '%s' \ ",MONTH,YearMonth); sqlstmt.len = strlen((char *)sqlstmt.arr); EXEC SQL WHENEVER SQLERROR GOTO sql_error; EXEC SQL PREPARE S2 FROM :sqlstmt; EXEC SQL DECLARE C2 CURSOR FOR S2; EXEC SQL OPEN C2; EXEC SQL WHENEVER NOT FOUND DO break; while(1){ EXEC SQL FETCH C2 INTO :Data; Data.arr[Data.len] = NULL; Month= (MONTH_REC *)alloc_Month(Month); strcpy(Month->Data,(char *)Data.arr); } EXEC SQL WHENEVER NOT FOUND CONTINUE; EXEC SQL CLOSE C2; EXEC SQL WHENEVER SQLERROR CONTINUE; sql_error: Sql_Error(__FILE__,__LINE__); Sql_Rollback(__FILE__,__LINE__); Exit(ERROR,__FILE__,__LINE__); return -1; } MONTH_REC *alloc_Month(MONTH_REC *Month) { int i; if(!Month){ Month= (MONTH_REC *)malloc(sizeof(struct Month_t)); Month_top = Month; }else{ Month->after= (MONTH_REC *)malloc(sizeof(struct Month_t)); Month = Month->after; } if(!Month){ Exit(ERROR,__FILE__,__LINE__); } memset(Month,NULL,sizeof(struct Month_t)); Month_end = Month; return Month; } MONTH *Get_Month_top() { return Month_top; } パラメータの値ですが、不思議なことにalloc_Month関数の前までは"111"など正常値が入っているのですが、戻ってくるとData.arrが0x000x00x00に変化してしまいます。またMonthも0x00になってしまいます。
補足
alloc_Month()関数はNULLではありませんでしたが、strcpy(Month->Data,(char *)Data.arr); 手前でMonth->Dataをチェックしてみると「Bad Address」とメッセージが返されてしまいました。尚、今は memset(Month,NULL,sizeof(struct Month_t)); のNULLは一応、0に置き換えています。