Как локальная переменная с плавающей точкой может быть повреждена в Java (Android 8.0.0)? - PullRequest
0 голосов
/ 30 сентября 2019

ОБНОВЛЕНО со значительной новой информацией (см. Внизу)

ИЗМЕНЕНО с улучшенным кодом регистрации

Я отслеживаю некоторые графические искажения в нашем приложении и отследил их до этой функции (котораяЯ обильно обсыпал ведение журнала):

public final int p_PostDraw(){
    bb_std_lang.print("Dissolve encountered.");
    float t_d=c_GColour.m_dissolve;
    bb_std_lang.print("Cached dissolve value locally: "+c_GColour.m_dissolve+ " " + t_d);
    c_GColour.m_dissolve=c_Gel.m_colstack.p_Top().m_a;
    bb_std_lang.print("Updated dissolve value: " + c_GColour.m_dissolve);
    c_Gel.m_colstack.p_Top().m_a=1.0f;
    bb_std_lang.print("Monitoring t_d="+t_d);
    super.p_PostDraw();
    bb_std_lang.print("Monitoring t_d="+t_d);
    c_GColour.m_dissolve=t_d;
    bb_std_lang.print("Dissolve post restore " + c_GColour.m_dissolve);
    return 0;
}

Большую часть времени это работает, как и ожидалось, но в определенный момент в игре это записывается:

09-30 14:40:59.086 10545-11101/? I/[Monkey]: Dissolve encountered.
09-30 14:40:59.086 10545-11101/? I/[Monkey]: Cached dissolve value locally: 1.0 1.0
09-30 14:40:59.086 10545-11101/? I/[Monkey]: Updated dissolve value: 0.1
09-30 14:40:59.086 10545-11101/? I/[Monkey]: Monitoring t_d=1.0
09-30 14:40:59.087 10545-11101/? I/[Monkey]: Monitoring t_d=-1.6314132E-19
09-30 14:40:59.087 10545-11101/? I/[Monkey]: Dissolve post restore -1.6314132E-19

Чтобы сломатьэто для вас: статическое значение m_dissolve копируется в локальную переменную t_d и имеет значение 1.0f. Статическое значение затем изменяется на 0,1f и используется при рендеринге дочерних объектов. Когда это будет завершено, локальная переменная t_d снова регистрируется перед использованием для восстановления статического значения, но тем временем таинственным образом становится -1.6314132E-19 (это значение кажется непредсказуемо разным каждый раз).

Мне неизвестно, каким образом локальная переменная Java может быть повреждена таким образом.

ОБНОВЛЕНИЕ:

В качестве теста я сделалt_d - переменная-член класса, содержащая приведенный выше код (а не локальную переменную), и ее значение больше не повреждено.

В качестве дополнительного теста я затем добавил несколько локальных переменных с плавающей запятой (от m_e до m_j)которые использовались ни для чего, кроме распечатки до и после super.p_PostDraw (). Вот что произошло:

09-30 15:20:51.219 28384-28877/? I/[Monkey]: M_E ETC BEFORE: 1.0 1.0 1.0 1.0 1.0 1.0
09-30 15:20:51.220 28384-28877/? I/[Monkey]: M_E ETC AFTER: 6.7E-44 6.7E-44 6.7E-44 6.7E-44 6.7E-44 6.7E-44

Затем я удалил все фильтры из logcat и обнаружил, что это скрывается между этими двумя строками:

09-30 15:20:51.219 28384-28877/? I/[Monkey]: M_E ETC BEFORE: 1.0 1.0 1.0 1.0 1.0 1.0
09-30 15:20:51.220 28384-28877/? I/zygote64: Deoptimizing int app.hidden.name.c_IffLT.p_Update4(app.hidden.name.c_Gel) due to JIT inline cache
09-30 15:20:51.220 28384-28877/? I/zygote64: Deoptimizing int app.hidden.name.c_Delay.p_Pump2(app.hidden.name.c_Gel) due to JIT inline cache
09-30 15:20:51.220 28384-28877/? I/zygote64: Deoptimizing int app.hidden.name.c_SetUniform_4F.p_Update4(app.hidden.name.c_Gel) due to JIT inline cache
09-30 15:20:51.220 28384-28877/? I/zygote64: Deoptimizing int app.hidden.name.c_EX_VarString.p_Set7(app.hidden.name.c_Expression) due to JIT inline cache
09-30 15:20:51.220 28384-28877/? I/zygote64: Deoptimizing java.lang.String app.hidden.name.c_EX_Format.p_AsString() due to JIT inline cache
09-30 15:20:51.220 28384-28877/? I/zygote64: Deoptimizing int app.hidden.name.c_IffNotEqual.p_Update4(app.hidden.name.c_Gel) due to JIT inline cache
09-30 15:20:51.220 28384-28877/? I/zygote64: Deoptimizing int app.hidden.name.c_PinVP.p_Update4(app.hidden.name.c_Gel) due to JIT inline cache
09-30 15:20:51.220 28384-28877/? I/[Monkey]: M_E ETC AFTER: 6.7E-44 6.7E-44 6.7E-44 6.7E-44 6.7E-44 6.7E-44

ОБНОВЛЕНИЕ:

Я настроил приведенный выше код для установки локальных переменных на разные значения, а не на все 1.0f, и это произошло:

09-30 15:56:37.686 1815-2373/? I/[Monkey]: M_E BEFORE: 2.0 1.0 3.0 4.0 5.0 1.0
09-30 15:56:37.687 1815-2373/? I/zygote64: Deoptimizing int app.hidden.name.c_IffLT.p_Update4(app.hidden.name.c_Gel) due to JIT inline cache
09-30 15:56:37.687 1815-2373/? I/zygote64: Deoptimizing int app.hidden.name.c_Delay.p_Pump2(app.hidden.name.c_Gel) due to JIT inline cache
09-30 15:56:37.687 1815-2373/? I/zygote64: Deoptimizing int app.hidden.name.c_SetUniform_4F.p_Update4(app.hidden.name.c_Gel) due to JIT inline cache
09-30 15:56:37.687 1815-2373/? I/zygote64: Deoptimizing int app.hidden.name.c_EX_VarString.p_Set7(app.hidden.name.c_Expression) due to JIT inline cache
09-30 15:56:37.688 1815-2373/? I/zygote64: Deoptimizing java.lang.String app.hidden.name.c_EX_Format.p_AsString() due to JIT inline cache
09-30 15:56:37.688 1815-2373/? I/zygote64: Deoptimizing int app.hidden.name.c_IffNotEqual.p_Update4(app.hidden.name.c_Gel) due to JIT inline cache
09-30 15:56:37.688 1815-2373/? I/zygote64: Deoptimizing int app.hidden.name.c_PinVP.p_Update4(app.hidden.name.c_Gel) due to JIT inline cache
09-30 15:56:37.688 1815-2373/? I/[Monkey]: M_E AFTER: 2.0 -5.6063644E-30 3.0 4.0 5.0 -5.6063644E-30

Другими словами, только локальная переменная, установленная на 1.0f, былаповрежден. Не первый объявленный или что-то еще, просто тот, который установлен на 1.0f. Затем я попытался установить все локальные переменные на разные номера ДРУГИЕ, чем 1.0f и не произошло искажения .

Конечно, должен быть какой-то приз за самую неясную ошибку в истории? Что локальная переменная будет повреждена, если ART деоптимизирует функции, но только если эта локальная переменная имеет значение 1,0?

1 Ответ

0 голосов
/ 30 сентября 2019

Мне неизвестно, каким образом локальная переменная Java может быть повреждена таким образом.

Это может произойти, если какой-то нативный код где-то попирает фрейм стека, содержащийt_d переменная.

Это также может произойти, если в этом разделе есть состояние гонки или опасность для памяти:

   float t_d=c_GColour.m_dissolve;
   bb_std_lang.print("Dissolve pre stack: " + c_GColour.m_dissolve);

Если вы внимательно посмотрите, вы на самом деле не печатаете t_d,То, что вы делаете, печатает (кажущееся) значение c_GColour.m_dissolve ... после , которое было присвоено t_d. Возможно, он изменился.

(Обратите внимание, что вы обращаетесь к пустой переменной m_dissolve, очевидно, без какой-либо синхронизации. Здесь есть потенциальное состояние гонки, даже если m_disolve объявлено как volatile.)

...