mallocの結果がゼロ?
-
なみき
mallocの結果がゼロ?
ルネサスのコンパイラでマイコンを開発してみようと、
プログラムを組んでみたのですが
思い通り動かないところがあります。
以下のコードがあります。 実行結果は
buff_size: 1024
malloc(buff_size): 0
となります。
mallocの値が0というのがよく判らないのですが、なんらかの理由で
ヒープ領域の確保に失敗したから0になったのでしょうか。
このような経験のある方はいらっしゃいませんか?
プログラムを組んでみたのですが
思い通り動かないところがあります。
以下のコードがあります。 実行結果は
buff_size: 1024
malloc(buff_size): 0
となります。
mallocの値が0というのがよく判らないのですが、なんらかの理由で
ヒープ領域の確保に失敗したから0になったのでしょうか。
このような経験のある方はいらっしゃいませんか?
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: mallocの結果がゼロ?
OSが存在するのか?とかヒープ領域はC言語のライブラリでどう管理されているのか?とか確認されましたか?
OSが存在しない環境だとスタートアップルーチンで初期化しなければいけないとか、パソコン系C言語ではやらない事をしないと動きませんよ。
[追記]
開発環境やら詳細を明かしてもらえばこちらでも調べられます。
ルネサスのマイコンなんて少なくとも十種類ぐらいあるのでは?バリエーションを加えたらとんでもない数のはずです。
OSが存在しない環境だとスタートアップルーチンで初期化しなければいけないとか、パソコン系C言語ではやらない事をしないと動きませんよ。
[追記]
開発環境やら詳細を明かしてもらえばこちらでも調べられます。
ルネサスのマイコンなんて少なくとも十種類ぐらいあるのでは?バリエーションを加えたらとんでもない数のはずです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: mallocの結果がゼロ?
詳しいことはよくわかりませんが、そもそも、
malloc()の結果を"%d"で出力することは正しいのでしょうか。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。
プログラムは思ったとおりには動かない。書いたとおりに動く。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: mallocの結果がゼロ?
正しいか正しく無いかと言えばC言語の規格としてみれば正しくないでしょうが、何らかの値が表示される可能性は非常に高いです。
ちなみに、%pにしたほうが良いと思われたのであればboxさんが、ちゃんと書いてあげてくださいね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: mallocの結果がゼロ?
私は質問者さん自身に考えてほしいと思っています。softya(ソフト屋) さんが書きました: %pにしたほうが良いと思われたのであればboxさんが、ちゃんと書いてあげてくださいね。
ちゃんと書くかどうかは、私の考えによります。
softyaさんの考えとは一致しないかもしれませんが、それはそれで仕方がないことです。
# ちゃんと書いてあげて、なんて言われたくなかった。なんかガッカリ。
最後に編集したユーザー box on 2011年8月05日(金) 22:42 [ 編集 3 回目 ]
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。
プログラムは思ったとおりには動かない。書いたとおりに動く。
-
なみき
Re: mallocの結果がゼロ?
HEW SHコンパイラでOSはありません。 雑誌に付録としてついてきたsh7262です。
内容をお見せしたいのですが、ちょっと規模が大きくなっていて、
コードの抜粋が難しくなっています。
boxさんのおっしゃるとおり、(unsigned char *)malloc(buff_size) では
駄目かも知れません。
ためしにassertするとabort()に飛ばされてしまうので、
評価結果が偽(0)であることは間違いないようです。
ヒープ領域がちゃんと確保できなくて 0 になっているのだと仮定して
もう少しメモリ周りの設定を見直してみます。
内容をお見せしたいのですが、ちょっと規模が大きくなっていて、
コードの抜粋が難しくなっています。
boxさんのおっしゃるとおり、(unsigned char *)malloc(buff_size) では
駄目かも知れません。
ためしにassertするとabort()に飛ばされてしまうので、
評価結果が偽(0)であることは間違いないようです。
ヒープ領域がちゃんと確保できなくて 0 になっているのだと仮定して
もう少しメモリ周りの設定を見直してみます。
Re: mallocの結果がゼロ?
確か、sbrk関数を定義するなど、適切な設定が必要になるはずです。なみき さんが書きました:HEW SHコンパイラでOSはありません。
そうしないと、ターゲットボードによってメモリマップが異なるので、ヒープをどのアドレスから何バイト割り当てるのか、処理系が知るすべがないからです。
いずれにせよ、まずはドキュメントを熟読することをお勧めします。
http://documentation.renesas.com/jpn/pr ... optimz.pdf
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: mallocの結果がゼロ?
高木さんの示された資料にヒープ領域の確保方法がかかれてますね。よく読んでみてください。
mallocの失敗した時の戻り値は、偽(0)でもなく数値0でもなくNULLと考えるのが正しいです。大半の処理系は0と同じですけどね。
なので
assert(malloc(buff_size)!=NULL);
が正しいです。
あとboxさんの言いたかったことを推測で書くと、「整数型とポインタでは型が違うので、整数型の書式である%dで安易に代用できる思わないほうが良い」って事なのでは無いでしょうか。なみきさんにうまく伝わっているか心配だったので書かせて頂きました。なみき さんが書きました:boxさんのおっしゃるとおり、(unsigned char *)malloc(buff_size) では
駄目かも知れません。
ためしにassertするとabort()に飛ばされてしまうので、
評価結果が偽(0)であることは間違いないようです。
mallocの失敗した時の戻り値は、偽(0)でもなく数値0でもなくNULLと考えるのが正しいです。大半の処理系は0と同じですけどね。
なので
assert(malloc(buff_size)!=NULL);
が正しいです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: mallocの結果がゼロ?
SHだというのは後出しの情報ですからね...。softya(ソフト屋) さんが書きました:mallocの失敗した時の戻り値は、偽(0)でもなく数値0でもなくNULLと考えるのが正しいです。大半の処理系は0と同じですけどね。
仮にH8とかだった場合、int型は16ビットですが、ポインタ型は32ビット、しかもビッグエンディアンです。
%dを使うと上位16ビットしか表示されませんから、もし下位16ビットが非ゼロだとしても、mallocの返却値がゼロだと誤認してしまいます。
未定義の動作に依存したプログラミングをしていることがそもそもの間違いですね。
-
なみき
Re: mallocの結果がゼロ?
HEWにて初期設定のヒープサイズを0x400から0x800に拡張することで
解決しました(非ゼロの値が返ってきた、というだけで詳しくは検証していませんが・・・)。
たかぎさんのおっしゃることも分かりましたので、
double型やそれ以上のビットを扱う場合の検証に適当に%dを使うのはもう止めます。
で、これと関係あるかどうか不明ですが、次のような関数を
組み込んでみたところ、次のような関数でエラーが出てしまいました。
また定数は次のように定義されています。
#define NMEA_CONVSTR_BUF (256)
コンソールの表示結果は
buf:3349.896
res:%f
となりました。文字列変数bufは3349.896で意図した変数です。
strtod関数はコンパイラの通りですから、
浮動小数点resがちゃんと得られてもいい筈ですが・・・
解決しました(非ゼロの値が返ってきた、というだけで詳しくは検証していませんが・・・)。
たかぎさんのおっしゃることも分かりましたので、
double型やそれ以上のビットを扱う場合の検証に適当に%dを使うのはもう止めます。
で、これと関係あるかどうか不明ですが、次のような関数を
組み込んでみたところ、次のような関数でエラーが出てしまいました。
double nmea_atof(const char *str, int str_sz)
{
char *tmp_ptr;
char buff[NMEA_CONVSTR_BUF];
double res = 0;
if(str_sz < NMEA_CONVSTR_BUF)
{
memcpy(&buff[0], str, str_sz);
buff[str_sz] = '\0';
t_printf("buf:%s\n", &buff[0]); /* debug */
res = strtod(&buff[0], &tmp_ptr); /* 怪しい */
t_printf("res:%f\n", res); /* debug */
}
return res;
}
#define NMEA_CONVSTR_BUF (256)
コンソールの表示結果は
buf:3349.896
res:%f
となりました。文字列変数bufは3349.896で意図した変数です。
strtod関数はコンパイラの通りですから、
浮動小数点resがちゃんと得られてもいい筈ですが・・・
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: mallocの結果がゼロ?
t_printfに%fが実装されていないのでは?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
-
なみき
Re: mallocの結果がゼロ?
なるほど!その可能性がありますね。
言われて初めて気がつきました。
t_printfは簡易printf関数で、
これまでfloat型のコンソール表示に活用してきた関数です。
これがもしかしたらdoubleまで拡張されてない可能性もあります。
ソースを見せるのは簡単ですが、まずは自分で検証してみます。
言われて初めて気がつきました。
t_printfは簡易printf関数で、
これまでfloat型のコンソール表示に活用してきた関数です。
これがもしかしたらdoubleまで拡張されてない可能性もあります。
ソースを見せるのは簡単ですが、まずは自分で検証してみます。
-
なみき
Re: mallocの結果がゼロ?
%fも解決しました。簡易printfが%fに対応できないことが分かったので、
sprintf()でdoubleをstringに変換して%sで表示できました。
課題は簡単に解決しましたが、本当は%fが扱えるprintfを自作するよう
努力するのが本筋かも知れませんけど・・・
でも第三者の視点がすごく参考になりました。振り返ると単純な
見落としばかりだったように思います。
softyaさんをはじめ、皆さんお世話になりました。
sprintf()でdoubleをstringに変換して%sで表示できました。
課題は簡単に解決しましたが、本当は%fが扱えるprintfを自作するよう
努力するのが本筋かも知れませんけど・・・
でも第三者の視点がすごく参考になりました。振り返ると単純な
見落としばかりだったように思います。
softyaさんをはじめ、皆さんお世話になりました。