これからの季節に親子でハイキング! >>

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

このQ&Aに関連する最新のQ&A

A 回答 (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?)になることはないと思いますが?
    • 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

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


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

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


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

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

その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

このQ&Aに関連する人気のQ&A

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

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QC言語のHP-UXからLinuxへのポーティング

C言語で開発されたプログラムをHP-UXからLinuxへのポーティングする場合、どのように行えば効率的でしょうか?
また、注意する内容があれば教えて頂けないでしょうか?

ポーティング前のOSはHP-UX(詳細不明)
ポーティング後のOSはRedHat Enterprise Linux 5.5 (64bit)
C言語で開発されたプログラムは、ソケット通信でサーバ間通信を行う機能となります

Aベストアンサー

unix系(linux含む)でポーティングの際におもに注意すべき点は以下の3つです。
1.OS固有の問題
2.32ビット版と64ビット版との違い
3.エンディアンの違い(ビッグエンディアンとリトルエンディアン)
今回は、どちらも64ビットなので、2については考慮しません。
1についてですが、
私がHP-UXからsolarisへ移植したときに、シグナルの動作が異なるときが
ありました。今回もし、シグナルを使用しているようでしたら、動作が
多少異なる覚悟をしておいたほうがよいかと思います。
また、IPC(セマフォ、メッセージキュー、共有メモリ)を使う場合、
共有メモリは、多少調整を行った記憶があります。
(hp-ux=>solaris=>linuxの移植で、hp-ux=>solarisはOK、
solaris=>linuxで多少の調整が必要でした)
結論としては、もしシグナルおよびIPCを使う場合、100%そのまま使用可能とは
考えないほうが良いです。
2についてですが、
HP-UXはビッグエンディアンのCPU(sunのsparc系など)であり、
red-hatはリトルエンディアン(intel系)のCPUになります。
このため、受信した電文がバイナリデータの場合、そのデータの中身を見るのであれば、
ビッグエンディアンからリトルエンディアンへの変換が必要になります。
データの中身は一切参照しないか、文字データなら変換の必要はありません。
また、IPアドレスおよびポート番号などは
htonl,htonsなどにより適切なエンディアンにする必要があります。
(HP-UXはビッグエンディアンなのでこのような操作(エンディアン変換)をしなくても正しく動作しますが、red-hatに移植すると動作しなくなる可能性があります。)
エンディアンの問題はソケット通信のプログラムだけでなく、そのデータを使用するほかのプログラムにも影響します。
エンディアンの問題は非常に重要ですので、もし、エンディアンについての知識が浅い場合は、
ネットで調査および自分で簡単なテストプログラムを作成し、十分に理解されることをお勧めします。

参考URL:http://www.katto.comm.waseda.ac.jp/~katto/Class/GazoTokuron/code/socket.html

unix系(linux含む)でポーティングの際におもに注意すべき点は以下の3つです。
1.OS固有の問題
2.32ビット版と64ビット版との違い
3.エンディアンの違い(ビッグエンディアンとリトルエンディアン)
今回は、どちらも64ビットなので、2については考慮しません。
1についてですが、
私がHP-UXからsolarisへ移植したときに、シグナルの動作が異なるときが
ありました。今回もし、シグナルを使用しているようでしたら、動作が
多少異なる覚悟をしておいたほうがよいかと思います。
また、IP...続きを読む


人気Q&Aランキング