Android 8.0でfloat変数のメモリ領域が破壊される。
Android 8.0以降で発生しています。
画像をディスプレイサイズに合わせて加工する処理があります。
そこで、ディスプレイサイズをfloatの変数に格納しているのですが、
その値が、突然変更(破壊)される現象が発生しております。
発生手順
- ディスプレイサイズをfloatの変数に格納する。
Bitmap.create*
の使用Bitmap.create*
の使用前後で、ディスプレイサイズを格納したfloat変数の値が変わる。(壊れる?)
問題は上記の3番で、現象としては、Bitmap.create*
の使用で、float変数のメモリ領域が
破壊されているように見えます。
floatの変数の型をdoubleやint等に変更すると本現象は発生しないことは確認しております。
変数の値は必ずしも壊れるわけではなく、壊れない場合もあります。
根本の原因が分からないため、暫定的な対応しかできない状態です。
本現象の原因をご存知の方がいれば、原因をご教示頂けないでしょうか?
開発環境
- OS:Mac OS 10.11.6
- Android Studio: 2.3.3, 3.0
- compileSdkVersion: 23
- buildToolVersion: 23.0.3
- minSdkVersion:14
- targetSdkVersion:23
発生端末
- Nexus5X
- Android 8.0, 8.1
- Qualcomm Snapdragon 808 (MSM8992) 1.8GHz+1.4GHz ヘキサコア
- メインメモリ 2GB
コードとログ
以下、該当のコードとなります。(抜粋)
// ディスプレイサイズをfloat変数に格納
float displayWidth = getResources().getDisplayMetrics().widthPixels;
float displayHeight = getResources().getDisplayMetrics().heightPixels;
float density = getResources().getDisplayMetrics().density;
try {
writeLog(LOG_TAG, "image1_1 dw:[" + displayWidth + "] dh:[" + displayHeight + "]");
Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.image1);
writeLog(LOG_TAG, "image1_2 dw:[" + displayWidth + "] dh:[" + displayHeight + "] bw:[" + bmp.getWidth() +"] bh:[" + bmp.getHeight() + "]");
float widthScale = (float)displayWidth / (float) bmp.getWidth();
writeLog(LOG_TAG, "image1_3 dw:[" + displayWidth + "] dh:[" + displayHeight + "] bw:[" + bmp.getWidth() +"] bh:[" + bmp.getHeight() + "] scale:[" + widthScale + "]");
bmp = Bitmap.createScaledBitmap(bmp, (int)(bmp.getWidth() * widthScale), (int)(bmp.getHeight() * widthScale), true);
writeLog(LOG_TAG, "image1_4 dw:[" + displayWidth + "] dh:[" + displayHeight + "] bw:[" + bmp.getWidth() +"] bh:[" + bmp.getHeight() + "] scale:[" + widthScale + "]");
ImageView imageView1 = (ImageView) findViewById(R.id.imageView1);
writeLog(LOG_TAG, "image1_5 dw:[" + displayWidth + "] dh:[" + displayHeight + "] bw:[" + bmp.getWidth() +"] bh:[" + bmp.getHeight() + "] scale:[" + widthScale + "]");
bmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), (int) ((float)displayHeight * 0.18f - 6.0f * density));
writeLog(LOG_TAG, "image1_6 dw:[" + displayWidth + "] dh:[" + displayHeight + "] bw:[" + bmp.getWidth() +"] bh:[" + bmp.getHeight() + "] scale:[" + widthScale + "]");
imageView1.setImageBitmap(bmp);
writeLog(LOG_TAG, "image1_7 dw:[" + displayWidth + "] dh:[" + displayHeight + "] bw:[" + bmp.getWidth() +"] bh:[" + bmp.getHeight() + "] scale:[" + widthScale + "]");
} catch (Exception e) {
writeLog(LOG_TAG, "image1 exception", e, true);
}
出力されたログは以下の通りです。(抜粋)
: image1_1 dw:[1080.0] dh:[1794.0]
: image1_2 dw:[1080.0] dh:[1794.0] bw:[1916] bh:[646]
: image1_3 dw:[1080.0] dh:[1794.0] bw:[1916] bh:[646] scale:[0.56367433]
: image1_4 dw:[1080.0] dh:[1794.0] bw:[1080] bh:[364] scale:[0.56367433]
: image1_5 dw:[1080.0] dh:[1794.0] bw:[1080] bh:[364] scale:[0.56367433]
: image1_6 dw:[1.4644055E-27] dh:[1794.0] bw:[1080] bh:[307] scale:[0.56367433]
: image1_7 dw:[1.4644055E-27] dh:[1794.0] bw:[1080] bh:[307] scale:[0.56367433]
上記の通り、ログのimage1_5
とimage1_6
の間(Bitmap.createBitmap
処理の後)で、
参照も代入もしていないdisplayWidth
の値が1080
から1.4644055E-27
に変わります。
変わる値は固定ではなく、実行のたびに変わります。