ページ 11

mallocの結果がゼロ?

Posted: 2011年8月05日(金) 21:19
by なみき
ルネサスのコンパイラでマイコンを開発してみようと、
プログラムを組んでみたのですが
思い通り動かないところがあります。

以下のコードがあります。

コード:

printf("buff_size: %d\n", buff_size);
printf("malloc(buff_size): %d\n", malloc(buff_size));
実行結果は
buff_size: 1024
malloc(buff_size): 0
となります。

mallocの値が0というのがよく判らないのですが、なんらかの理由で
ヒープ領域の確保に失敗したから0になったのでしょうか。
このような経験のある方はいらっしゃいませんか?

Re: mallocの結果がゼロ?

Posted: 2011年8月05日(金) 21:51
by softya(ソフト屋)
OSが存在するのか?とかヒープ領域はC言語のライブラリでどう管理されているのか?とか確認されましたか?
OSが存在しない環境だとスタートアップルーチンで初期化しなければいけないとか、パソコン系C言語ではやらない事をしないと動きませんよ。

[追記]
開発環境やら詳細を明かしてもらえばこちらでも調べられます。
ルネサスのマイコンなんて少なくとも十種類ぐらいあるのでは?バリエーションを加えたらとんでもない数のはずです。

Re: mallocの結果がゼロ?

Posted: 2011年8月05日(金) 22:21
by box
なみき さんが書きました:

コード:

printf("malloc(buff_size): %d\n", malloc(buff_size));
詳しいことはよくわかりませんが、そもそも、
malloc()の結果を"%d"で出力することは正しいのでしょうか。

Re: mallocの結果がゼロ?

Posted: 2011年8月05日(金) 22:27
by softya(ソフト屋)
box さんが書きました:
なみき さんが書きました:

コード:

printf("malloc(buff_size): %d\n", malloc(buff_size));
詳しいことはよくわかりませんが、そもそも、
malloc()の結果を"%d"で出力することは正しいのでしょうか。
正しいか正しく無いかと言えばC言語の規格としてみれば正しくないでしょうが、何らかの値が表示される可能性は非常に高いです。
ちなみに、%pにしたほうが良いと思われたのであればboxさんが、ちゃんと書いてあげてくださいね。

Re: mallocの結果がゼロ?

Posted: 2011年8月05日(金) 22:31
by box
softya(ソフト屋) さんが書きました: %pにしたほうが良いと思われたのであればboxさんが、ちゃんと書いてあげてくださいね。
私は質問者さん自身に考えてほしいと思っています。
ちゃんと書くかどうかは、私の考えによります。
softyaさんの考えとは一致しないかもしれませんが、それはそれで仕方がないことです。

# ちゃんと書いてあげて、なんて言われたくなかった。なんかガッカリ。

Re: mallocの結果がゼロ?

Posted: 2011年8月05日(金) 22:37
by なみき
HEW SHコンパイラでOSはありません。 雑誌に付録としてついてきたsh7262です。
内容をお見せしたいのですが、ちょっと規模が大きくなっていて、
コードの抜粋が難しくなっています。

boxさんのおっしゃるとおり、(unsigned char *)malloc(buff_size) では
駄目かも知れません。
ためしにassertするとabort()に飛ばされてしまうので、
評価結果が偽(0)であることは間違いないようです。

ヒープ領域がちゃんと確保できなくて 0 になっているのだと仮定して
もう少しメモリ周りの設定を見直してみます。

Re: mallocの結果がゼロ?

Posted: 2011年8月05日(金) 23:04
by たかぎ
なみき さんが書きました:HEW SHコンパイラでOSはありません。
確か、sbrk関数を定義するなど、適切な設定が必要になるはずです。
そうしないと、ターゲットボードによってメモリマップが異なるので、ヒープをどのアドレスから何バイト割り当てるのか、処理系が知るすべがないからです。
いずれにせよ、まずはドキュメントを熟読することをお勧めします。
http://documentation.renesas.com/jpn/pr ... optimz.pdf

Re: mallocの結果がゼロ?

Posted: 2011年8月05日(金) 23:21
by softya(ソフト屋)
高木さんの示された資料にヒープ領域の確保方法がかかれてますね。よく読んでみてください。
なみき さんが書きました:boxさんのおっしゃるとおり、(unsigned char *)malloc(buff_size) では
駄目かも知れません。
ためしにassertするとabort()に飛ばされてしまうので、
評価結果が偽(0)であることは間違いないようです。
あとboxさんの言いたかったことを推測で書くと、「整数型とポインタでは型が違うので、整数型の書式である%dで安易に代用できる思わないほうが良い」って事なのでは無いでしょうか。なみきさんにうまく伝わっているか心配だったので書かせて頂きました。
mallocの失敗した時の戻り値は、偽(0)でもなく数値0でもなくNULLと考えるのが正しいです。大半の処理系は0と同じですけどね。
なので
assert(malloc(buff_size)!=NULL);
が正しいです。

Re: mallocの結果がゼロ?

Posted: 2011年8月05日(金) 23:31
by たかぎ
softya(ソフト屋) さんが書きました:mallocの失敗した時の戻り値は、偽(0)でもなく数値0でもなくNULLと考えるのが正しいです。大半の処理系は0と同じですけどね。
SHだというのは後出しの情報ですからね...。
仮にH8とかだった場合、int型は16ビットですが、ポインタ型は32ビット、しかもビッグエンディアンです。
%dを使うと上位16ビットしか表示されませんから、もし下位16ビットが非ゼロだとしても、mallocの返却値がゼロだと誤認してしまいます。
未定義の動作に依存したプログラミングをしていることがそもそもの間違いですね。

Re: mallocの結果がゼロ?

Posted: 2011年8月07日(日) 00:03
by なみき
HEWにて初期設定のヒープサイズを0x400から0x800に拡張することで
解決しました(非ゼロの値が返ってきた、というだけで詳しくは検証していませんが・・・)。
たかぎさんのおっしゃることも分かりましたので、
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がちゃんと得られてもいい筈ですが・・・

Re: mallocの結果がゼロ?

Posted: 2011年8月07日(日) 01:32
by softya(ソフト屋)
t_printfに%fが実装されていないのでは?

Re: mallocの結果がゼロ?

Posted: 2011年8月07日(日) 10:09
by なみき
なるほど!その可能性がありますね。
言われて初めて気がつきました。

t_printfは簡易printf関数で、
これまでfloat型のコンソール表示に活用してきた関数です。
これがもしかしたらdoubleまで拡張されてない可能性もあります。
ソースを見せるのは簡単ですが、まずは自分で検証してみます。

Re: mallocの結果がゼロ?

Posted: 2011年8月07日(日) 11:42
by なみき
%fも解決しました。簡易printfが%fに対応できないことが分かったので、
sprintf()でdoubleをstringに変換して%sで表示できました。

課題は簡単に解決しましたが、本当は%fが扱えるprintfを自作するよう
努力するのが本筋かも知れませんけど・・・

でも第三者の視点がすごく参考になりました。振り返ると単純な
見落としばかりだったように思います。
softyaさんをはじめ、皆さんお世話になりました。