お世話になります。
標記の件ですが、returnの前までは処理が行われているようなのですが、
そこで止まっているようなのです。
このような事象が発生するものとして考えられる原因はありますでしょうか。
ご教授お願い致します。
<コード>
int sub1(unsigned short aa, char bb)
{
int iRet = 0;
for(条件)
{
iRet = sub2( cc, &dd );
printf(%d\n, iRet);
if ( iRet == -1)
{
printf(------NG sub2()\n);
}
printf(------OK sub2()\n);
}
}
int sub2(struct aa, char *bb)
{
//処理・・・
printf(BEFORE RETURN\n, iRet);
return (0);
}
<実行結果>
BEFORE RETURN
(※sub2を呼び出した後のprintfの内容が全く表示されません。)
<環境>
WinXP, .NET
これ、ちゃんとコンパイルできませんよ。
sub2() 内で iRet にアクセスできませんから。
現象を再現できる最小限の正しいコードを示してください。
すみません。ご指摘の通りsub2()のiRetは不要ですね。
(誤) printf(BEFORE RETURN\n, iRet);
(正) printf(BEFORE RETURN\n);
上記のような処理で、実行結果として
BEFORE RETURN
しか表示されず、プロセスが上がったままの状態になってしまうのです。
ccあるいは、struct aaとはなんぞや?
ccあるいは、struct aaとはなんぞや?
何度もすみません。
cc,struct aaは、構造体のポインタですが、
これを引数にしたほかの関数では戻ってくるようなので、
関係ないと思われます。
なので、無視していただいてかまいません。
<コード>
int sub1(unsigned short aa, char bb)
{
int iRet = 0;
char dd[5];
for(条件)
{
iRet = sub2( dd );
printf(%d\n, iRet);
if ( iRet == -1)
{
printf(------NG sub2()\n);
}
printf(------OK sub2()\n);
}
}
int sub2(char *bb)
{
//処理・・・
printf(BEFORE RETURN\n);
return (0);
}
デバッガーで動作を追ってみたらどうなりますか
sub2関数の中で、スタックを破壊していると思われます。
> sub2関数の中で、スタックを破壊していると思われます。
そのセンが濃厚ですねぇ。
だから '現象を再現できる最小限の正しいコードを示してください' なのに。
最低限がどこまでなのか絞り込めないようなら、
いっそのこと全文出してしまった方が問題が少ないと思いますよ。
私もREEさんの意見に賛成ですが、
実際には関数sub2に当たる全ソースを提示してもらわないと
なんともいえません。
あまりにも長いというのであれば問題ですが、
(ひとつの関数がそこまで長いというもの実は問題です。)
それにしたって省略のしかたが的を得ていないために
かえって掲示板を読んでる側を混乱させてしまってます。
掲示板を読んでいる人には公開されていない情報はわかりません。
公開可能な情報は基本的にすべて出してしまった方が無難だと考えてください。
呼び出し元に戻らないなら、十中八九はバッファオーバーフローによるスタック破壊な
んだろうね。
デバッガでコールスタックウィンドウを表示して sub2 関数内をステップ実行してみた
ら、どこかでコールスタックから呼び出し元の sub1 関数が見えなくなるんじゃない
の?
したら、その近辺のコードが悪さをしてる、ってことで。
今、sub2()の //処理・・ 部分を全て削除して適当なまとまりごとにコードを追加してい
ったところ、どうやらsprintf()でとまっているようでした。
(ですが、その下の処理は通っていました。)
これが、指摘されていた、スタックを破壊しているということなのだと思うのですが、
sprintf()でセットしているものが、スタックというものを破壊しているのでしょうか。
最後に、コードを省略したために、混乱させてしまいましてすみませんでした。
> これが、指摘されていた、スタックを破壊しているということなのだと思うのですが、
> sprintf()でセットしているものが、スタックというものを破壊しているのでしょうか。
sprintf()の第1引数に渡したバッファはsub2()内のローカル変数ではありませんか?
そして、そのバッファのサイズが小さいのではないでしょうか?
sprintf()自身はバッファのサイズに関しては関知しないので、バッファオーバーランで
sub2()から戻る際のアドレスが入った部分に上書きしてしまったのでしょう。
> どうやらsprintf()でとまっているようでした。(ですが、その下の処理は通っていまし
た。)
> sprintf()の第1引数に渡したバッファはsub2()内のローカル変数ではありませんか?
> そして、そのバッファのサイズが小さいのではないでしょうか?
#include <assert.h>
char buffer[N];
...
int n = sprintf(buffer, ...);
assert( n < N );
とかやってみれば一発でわかりそう。
sprintf()の第1引数に渡したバッファはsub2()内のローカル変数ではありませんか?
そして、そのバッファのサイズが小さいのではないでしょうか?
変換指定子でサイズを小さくちたところ正常に呼び出し元にもどることができました。
因みに、構造体のaaというメンバは後になって追加したものなのですが、
何か関係ありますでしょうか?
typedef struct stru
{
・
・
char aa[5];
}stru;
sub2()
{
unsigned long ss;
stru struG;
sprintf(struG.aa, %05u, ss); //エラーになります。
sprintf(struG.aa, %04u, ss); //呼び出し元に戻ることができました。
return 0;
}
関係大アリ。
%05u てことは '5文字分の幅で書け' です。
さらに終端の '\0' が追加されて 6文字。 char aa[5]; では不足します。
だから
int n = sprintf(struG.aa, .... );
assert( n < 5 );
すりゃ一発でわかるって書いたのに。