プロが教える店舗&オフィスのセキュリティ対策術

HP-UXへの移植で困っています。
strcpy(Month->Data,Data.arr);
というコードがあり、今まではDigital Unix上では正常に動作していました。しかしHP-UX上でコンパイル、実行するとセグメンテーション障害が発生し、正常に動作しません。
どなたか助けてください。

A 回答 (6件)

そのstrcpyでSEGVしているんなら、パラメータの値をチェックしました?


多分移植前のシステムでは正常動作していたってのは勘違いで、
未初期化のポインタを使ってたりしていたのがたまたま動いていただけで
HP-UXに持ってきたときにバグが顕在化しただけじゃないですか?

つか助けろって言われたってたったそれだけの情報じゃ無理だって。

この回答への補足

以下今回のコードです。
<Month.h>
typedef struct Month_tMONTH;
struct Month_t{
structMonth_t*after;
charData[8+1];
};
MONTH *Get_Month_top();

<Month.c>
staticMONTH_REC *alloc_Month();
staticMONTH_REC*Month_top;
staticMONTH_REC*Month_end;

int Read_Month()
{
EXEC SQL BEGIN DECLARE SECTION;
VARCHAR sqlstmt[4096];
VARCHARData[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)
{
inti;

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になってしまいます。

補足日時:2007/12/09 09:56
    • good
    • 0

構造体のメンバー 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();

補足日時:2007/12/09 20:04
    • good
    • 0

ここまで状況が絞り込めているのなら、デバッガでステップ実行すれば


すぐに場所をピンポイントで特定できそうな気がするんですが、
実は毎回発生するわけじゃなくて何かの拍子に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の部分を変更して実行してみます。

補足日時:2007/12/10 05:26
    • good
    • 0

私のコードの読み違いなら申し訳ないのですが、


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' かは、結局同じ値になるので、
私はコードの視認性を考え、その場に応じた書き方をするようにしています。

この回答への補足

alloc_Month()関数はNULLではありませんでしたが、strcpy(Month->Data,(char *)Data.arr);
手前でMonth->Dataをチェックしてみると「Bad Address」とメッセージが返されてしまいました。尚、今は
memset(Month,NULL,sizeof(struct Month_t));
のNULLは一応、0に置き換えています。

補足日時:2007/12/11 08:21
    • good
    • 0

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
    • good
    • 0

ひとつ気になった点があります。



#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?)になることはないと思いますが?
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!