我在jna中使用java中的Z3 C api。我经常获得无效的内存访问,但只能使用windows(.dll)和mac os(.dylib)库。当我使用linux(.so)时,它不会发生。
我暂时解决了这个问题,从来没有调用dec_ref
程序,包括ast和所有其他对象(我仍然称之为inc_ref
过程,我在mk_context_rc
处使用mk_context
开始)。当然,这种解决方案是不可持续的。
我想这是由于某处的内存管理。即使我只是使用Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x000000000000000c
Crashed Thread: 0 Dispatch queue: com.apple.main-thread
它仍然崩溃。
在线程JNA simple function call works on linux (x64) but not on windows (x86)中,用户遇到了类似的问题,结果发现这是由于某些编译配置造成的。
这是我得到的例外(在Mac OS X 10.6.8上)
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
这是失败的痕迹
{{1}}也许他们可以帮助我们理解我做错了什么
答案 0 :(得分:3)
根据您问题中的评论,您似乎正在使用仅在新Z3 API中提供的策略和其他功能。从版本4.0开始,引用计数是在Z3 API中管理内存的默认方法。 Z3 API仍支持旧内存管理策略(在使用API Z3_mk_context
而非Z3_mk_context_rc
时启用)。但是,旧的内存管理策略不适用于4.0版中引入的新对象(例如Solvers
,Tactics
,...)。
Z3发行版包含一个Python API。 Python API的源代码位于Z3发行版的子目录python
中。它演示了如何将Z3 API集成到托管语言(如Python)中。我相信可以使用类似的方法在Java中集成Z3 API。我们的想法是用Java对象包装器包装每个Z3对象。引用计数器应在构造函数中递增,并在Java垃圾收集器回收包装器时递减。
答案 1 :(得分:3)
引发异常是因为我的主程序和java垃圾收集器同时访问Z3。我解决了让Library
对象线程安全,用方法Native.synchronizedLibrary