ndkのサンプルのhellojniに下記コードを書きますと
コンパイルは通りますが、実行中に落ちます。
cygwinでmainに書いて、x86で実行するとOKです。
ndk r3でng
ndk r4でng
ndk r4bは入れてません。
①
jstring
Java_com_example_hellojni_HelloJni_stringFromJNI
( JNIEnv* env, jobject thiz )
{
__android_log_print(ANDROID_LOG_INFO, "jni", "ok");
typedef struct test2
{
int a;
int b;
long c;
}test2;
test2 * x42;
x42->a = 888;
__android_log_print(ANDROID_LOG_INFO, "jni", "ok");
return (*env)->NewStringUTF(env, "Hello from JNI !");
}
次のように、書き換えますと、実行されます。
②
typedef struct test2
{
int a;
int b;
long c;
};
struct test2 test2;
strust test2 * x42=&test2;
お願いは、①で落ちないよう。LOCAL_CFLAGSの
オプションを教えて下さい。
-std -ansi -pedantic等やってますが、正解見つかりません。
ndkのcflagの内容とかの情報もお願いします。
embeddedな方、お願いします。
こんにちは。sahdと申します。
構造体のポインタだけ宣言して、そのメンバに値を代入しているので、
大抵SIGSEGVが飛んでくるはずです。
2の方法では構造体の実体を宣言して、そこの実体の先頭アドレスを
ポインタに格納しているので、そのプロセスの領域であることが保証され、
正しく動作します。
ということだと思うのですが、間違っていたらスミマセン。
①は、cygwinで動きます。
無理やり、理解すると
typedef struct test2
{
...
}test2; <---ここで、構造体の確保。
test2 * x42; <---ここで、アドレスの取得。
こんなコード、gccの方言だと思いますが、なぜ
ndkでは、動かないのでしょう。
確かに、ndkでは、SIGSEGVで飛んでます。
ohisama
--
このメールは Google グループのグループ「日本Androidの会」の登録者に送られて
います。
このグループに投稿するには、android-g...@googlegroups.com にメールを
送信してください。
このグループから退会するには、
android-group-j...@googlegroups.com にメールを送信してくださ
い。
詳細については、http://groups.google.com/group/android-group-japan?hl=ja か
らこのグループにアクセスしてください。
SIGSEGVで落ちるのが正しい動作です。
cygwinで動いた(ように見える)のは偶然でしょう。
NDKとか何も関係ありません。
ポインター(x42)が何も指してませんよ。
(10/9/26 14:58), ohisamallc wrote:
> ①は、cygwinで動きます。
> 無理やり、理解すると
> typedef struct test2
> {
> ...
> }test2; <---ここで、構造体の確保。
別件ですが、構造体型名と、変数名が同一なので、たとえ
許されようとも書くべきではないでしょう。
> こんなコード、gccの方言だと思いますが、なぜ
> ndkでは、動かないのでしょう。
別に方言はないように思います。
heapをoverrunするとOSにすぐに殺されることが多いですが、
今壊しているのはstack領域上なので、殺されないことがあります。
もっと派手に壊すと、死ねると思います。
おそらく核心部分が質問者さんに伝わっていないのかもしれません。
『新しい構造体型の宣言はしているが、変数宣言がなされていない』
ということです。
> typedef struct test2 ←ここでは「構造体タグ名」が定義される
> {
> ...
> }test2; ←ここでは typedef による新しい「型」が定義される
上の記述は「構造体タグ名」と「型」がたまたま同じ test2 という名前で定義されただけであり、
「変数」は宣言されていません。つまり test2 という領域は確保されていないということです。
通常、構造体タグ名は必要ありません。構造体定義の内部に自分自身へのポインタを含む等のケースで必要になる程度です。
敢えて構造体タグ名も使うのであれば tagTest2 のように定義する型名とは明確に区別すべきでしょう。
typedef struct tagTest2 {
...
} Test2;
----------------
で、肝心の変数宣言です。
◆ 構造体タグ名を使うなら
struct tagTest2 t2;
struct tagTest2 *x42;
◆ typedef で定義した型名を使うなら
Test2 t2;
Test2 *x42;
----------------
私だったらこう書く、という例です。
typedef struct {
...
} Test2;
Test2 t2, *x42;
x42 = &t2;
・
・
・
※ ポインタへの代入を変数宣言と分けているあたりはC屋の古いスタイルかもしれません・・・気にしないでください(笑)
反論は、次の点だけです。
}test2; <--変数を同時に指定してると、思います。
確かにコードは、間違っていると思いますが、
結果が違うことに着目してます。
gcc 4.3.4(cygwin) 動く
gcc 4.2.1(ndk r4) 値は取れるがその後落ちる
gcc 4.4.0(ndk r4) 落ちる
結論は、gcc 4.3.4とgcc 4.2.1の挙動はおかしい。(偶然?)
成果は、gccの-mandoroidオプションを知りました。
皆さん、ご指導ありがとうございます。
> -----Original Message-----
> From: android-g...@googlegroups.com
> [mailto:android-g...@googlegroups.com]On Behalf Of amag
> Sent: Monday, September 27, 2010 12:00 AM
> To: android-g...@googlegroups.com
あ"っ。
(10/9/27 0:00), amag wrote:
>> }test2; ←ここでは typedef による新しい「型」が定義される
amagさんの指摘は正しいと私も思います。
私はtypedefを無視して、変数宣言だと解釈してしまいました。
これは誤った解釈でした。
#C++だと、もうtypedef struct...はほとんど書かないんですよねぇ。。
#言い分けになってない上に、もはや場違いの話題ですね。失礼しました。