Z3 вызывает недопустимый доступ к памяти с помощью JNA

Я использую Z3 C api в java с jna. Я часто получаю неверный доступ к памяти, но только с библиотеками windows (.dll) и mac os (.dylib). Этого не происходит, когда я использую linux one (.so).

Я временно решил эту проблему, никогда не вызывая dec_ref процедуры, как для ast, так и для всех других объектов (я все еще вызываю inc_ref процедуры и использую mk_context_rc в начале). Конечно, это решение неустойчиво.

Я предполагаю, что это связано с управлением памятью где-то. Даже если я просто использую mk_context, он все равно вылетает.

В потоке простая функция JNA call работает на linux (x64), но не на windows (x86), у пользователя возникла аналогичная проблема, и оказалось, что это произошло из-за некоторой конфигурации компиляции.

Это исключение, которое я получаю (в Mac OS X 10.6.8)

Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x000000000000000c
Crashed Thread:  0  Dispatch queue: com.apple.main-thread

и это след отказа

    Thread 0 Crashed:  Dispatch queue: com.apple.main-thread
0   libz3.dylib                     0x00000001250d4d64 unsigned int ast_array_hash<expr>(expr* const*, unsigned int, unsigned int) + 244
1   libz3.dylib                     0x00000001250cb16a ast_manager::register_node_core(ast*) + 36
2   libz3.dylib                     0x00000001250cbeae ast_manager::mk_app_core(func_decl*, unsigned int, expr* const*) + 134
3   libz3.dylib                     0x00000001250cc30d ast_manager::mk_app(func_decl*, unsigned int, expr* const*) + 749
4   libz3.dylib                     0x000000012528c194 map_proc::reconstruct(app*) + 214
5   libz3.dylib                     0x00000001254830b8 void for_each_expr_core<qe::lift_foreign_vars, obj_mark<expr, bit_vector, default_t2uint<expr> >, false, false>(qe::lift_foreign_vars&, obj_mark<expr, bit_vector, default_t2uint<expr> >&, expr*) + 760
6   libz3.dylib                     0x00000001254832c9 qe::lift_foreign_vars::lift(obj_ref<expr, ast_manager>&) + 61
7   libz3.dylib                     0x00000001254833a6 qe::datatype_plugin::simplify(obj_ref<expr, ast_manager>&) + 92
8   libz3.dylib                     0x000000012546b1a7 qe::quant_elim_plugin::check(unsigned int, app* const*, expr*, obj_ref<expr, ast_manager>&, bool, ref_vector<app, ast_manager>&, qe::def_vector*) + 535
9   libz3.dylib                     0x000000012546b8f9 qe::quant_elim_new::eliminate_block(unsigned int, app* const*, obj_ref<expr, ast_manager>&, ref_vector<app, ast_manager>&, bool, qe::def_vector*) + 445
10  libz3.dylib                     0x000000012545f2cb qe::quant_elim_new::eliminate_exists(unsigned int, app* const*, obj_ref<expr, ast_manager>&, ref_vector<app, ast_manager>&, bool, qe::def_vector*) + 67
11  libz3.dylib                     0x0000000125462170 qe::quant_elim_new::eliminate_exists_bind(unsigned int, app* const*, obj_ref<expr, ast_manager>&) + 88
12  libz3.dylib                     0x000000012545c0ba qe::expr_quant_elim::elim(obj_ref<expr, ast_manager>&) + 1012
13  libz3.dylib                     0x000000012545cb75 qe::expr_quant_elim::operator()(expr*, expr*, obj_ref<expr, ast_manager>&) + 113
14  libz3.dylib                     0x000000012548b993 qe_tactic::imp::operator()(ref<goal> const&, sref_buffer<goal>&, ref<model_converter>&, ref<proof_converter>&, obj_ref<dependency_manager<ast_manager::expr_dependency_config>::dependency, ast_manager>&) + 783
15  libz3.dylib                     0x00000001255debfa cleanup_tactical::operator()(ref<goal> const&, sref_buffer<goal>&, ref<model_converter>&, ref<proof_converter>&, obj_ref<dependency_manager<ast_manager::expr_dependency_config>::dependency, ast_manager>&) + 14
16  libz3.dylib                     0x00000001255d5e3d exec(tactic&, ref<goal> const&, sref_buffer<goal>&, ref<model_converter>&, ref<proof_converter>&, obj_ref<dependency_manager<ast_manager::expr_dependency_config>::dependency, ast_manager>&) + 109
17  libz3.dylib                     0x0000000125070ed8 _tactic_apply + 680
18  libz3.dylib                     0x00000001250711d9 Z3_tactic_apply + 105
19  jna4404318687023840668.tmp      0x000000010a00cd1c ffi_call_unix64 + 76
20  jna4404318687023840668.tmp      0x000000010a00c884 ffi_call + 644
21  jna4404318687023840668.tmp      0x000000010a003ca5 Java_com_sun_jna_Native_ffi_1prep_1cif + 1605
22  jna4404318687023840668.tmp      0x000000010a004282 Java_com_sun_jna_Native_invokePointer + 34
23  ???                             0x00000001031cfd2e 0 + 4347198766
24  ???                             0x00000001031cd658 0 + 4347188824
25  ???                             0xffb89c44ff5c4272 0 + 18426649695542329970

может они могут быть полезны, чтобы понять, что я делаю не так


person Mirco    schedule 03.09.2012    source источник
comment
Почему вы не вызываете ScalaZ3 из Java? Думаю, было бы намного проще.   -  person pad    schedule 03.09.2012
comment
В Windows собственный long имеет одинаковый размер для 32-битной и 64-битной систем. В OSX и Linux размер отличается. С какой аркой вы работаете на каждой платформе? Если вы работаете на разных дугах и не учитываете это в своем сопоставлении (кстати, вы не приводите никаких примеров - вы должны предоставить как собственные объявления, так и объявления JNA), вы получите ошибки памяти.   -  person technomage    schedule 04.09.2012
comment
Я работаю на Mac OS и Windows на 64-битных машинах, но Linux - 32-битный. Обратите внимание, что исключение возникает после многих вызовов этой процедуры, почти случайным образом, что я вижу.   -  person Mirco    schedule 04.09.2012
comment
ScalaZ3 не поддерживает многие функции, которые мне нужны (например, тактику), поэтому я использую jna.   -  person Mirco    schedule 04.09.2012
comment
Попробуйте запустить 64-разрядную версию Linux, вы, вероятно, увидите те же ошибки. И запустите OSX, используя 32-битную виртуальную машину (-d32 должен сделать это).   -  person technomage    schedule 05.09.2012
comment
Такая же ошибка в OSX с использованием 32-битной виртуальной машины   -  person Mirco    schedule 06.09.2012
comment
На самом деле, я понял, что если я буду держать его больше, я могу заставить его вылететь с любой аркой :-)   -  person Mirco    schedule 06.09.2012


Ответы (2)


Судя по комментариям в вашем вопросе, похоже, что вы используете тактику и другие функции, доступные только в новом Z3 API. Начиная с версии 4.0, подсчет ссылок является подходом по умолчанию для управления памятью в Z3 API. Z3 API по-прежнему поддерживает старую политику управления памятью (она включается, когда API Z3_mk_context используется вместо Z3_mk_context_rc). Однако старая политика управления памятью недоступна для новых объектов (таких как Solvers, Tactics, ...), которые были представлены в версии 4.0.

Дистрибутив Z3 содержит Python API. Исходный код Python API находится в подкаталоге python в дистрибутиве Z3. Он демонстрирует, как интегрировать Z3 API в управляемый язык, такой как Python. Я считаю, что аналогичный подход можно использовать для интеграции Z3 API в Java. Идея состоит в том, чтобы обернуть каждый объект Z3 оболочкой объекта Java. Счетчик ссылок должен увеличиваться в конструкторе и уменьшаться, когда сборщик мусора Java освобождает оболочку.

person Leonardo de Moura    schedule 06.09.2012
comment
Я именно этим и занимаюсь. Я создаю контекст с помощью mk_context_rc, увеличиваю счетчик ссылок в конструкторе и уменьшаю счетчик в деструкторе (финализации) каждой оболочки. Думаю, проблема в том, что одновременно работает сборщик мусора. Фактически, если я сохраню все объекты для уничтожения в синхронизированном списке, а затем уменьшу счетчики, прерывая выполнение основной программы, все работает. Так что я думаю, проблема заключалась в том, что я вызвал какое-то состояние гонки внутри Z3. Должна ли библиотека z3 быть потокобезопасной? - person Mirco; 06.09.2012

Исключение было вызвано тем, что моя основная программа и сборщик мусора java одновременно обращались к Z3. Я решил просто сделать объект Library потокобезопасным, обернув его методом Native.synchronizedLibrary

person Mirco    schedule 06.09.2012