c - 如何调试由于超出可用动态堆而导致的 Emscripten 段错误

标签 c emscripten

我正在尝试使用 Emscripten 编译一个开源库,在进行了一些小的更改后,我编译并运行了它,但是当我尝试实际使用它太多时,我得到:

segmentation fault, exceeded the top of the available dynamic heap when loading 1 bytes from address 1869770797. STATICTOP=184544, DYNAMICTOP=21213184 melt.html:1246:11
exception thrown: abort("segmentation fault, exceeded the top of the available dynamic heap when loading 1 bytes from address 1869770797. STATICTOP=184544, DYNAMICTOP=21213184") at jsStackTrace@http://localhost:6931/melt.js:1603:13
stackTrace@http://localhost:6931/melt.js:1620:12
abort@http://localhost:6931/melt.js:52047:44
SAFE_HEAP_LOAD@http://localhost:6931/melt.js:926:51
_strcmp@http://localhost:6931/melt.wasm:wasm-function[912]:0x67c58

但我真的不认为它应该使用那么多内存?在浏览器中使用 Emscripten 调试此类内存问题的最佳方法是什么?

我似乎甚至找不到它失败的确切“strcmp”调用,因为堆栈信息有点糟糕。

如果我在没有 -s SAFE_HEAP=1 的情况下进行编译,则会出现错误:

exception thrown: RuntimeError: index out of bounds,_strcmp@http://localhost:6931/melt.wasm:wasm-function[771]:0x34dcf
Module._strcmp@http://localhost:6931/melt.js:50463:10

我尝试编译的库是MLT框架( https://github.com/mltframework/mlt )

它有点复杂,而且它使用动态链接来加载其大部分功能 - 现在我只是想让它以绝对最小的速度工作 - mltframework 本身(静态链接到可执行文件),libmltcore(通过加载) dlload)、libmltsdl2(通过 dlload 加载)

对于 MLT 本身,编译标志如下(使用 WASM=0 但似乎与 WASM 无关):

emcc -g -s WASM=0 -dynamiclib -current_version 6.14.0 
-compatibility_version 6 
-o ../../../lib/libmlt.bc 
mlt_frame.o mlt_version.o mlt_geometry.o mlt_deque.o mlt_property.o mlt_properties.o mlt_events.o mlt_parser.o mlt_service.o mlt_producer.o mlt_multitrack.o mlt_playlist.o mlt_consumer.o mlt_filter.o mlt_transition.o mlt_field.o mlt_tractor.o mlt_factory.o mlt_repository.o mlt_pool.o mlt_tokeniser.o mlt_profile.o mlt_log.o mlt_cache.o mlt_animation.o mlt_slices.o  
-lpthread -lm

libmltcore:

emcc -g -s EXPORT_ALL=1 -s WASM=0 -s SIDE_MODULE=1 -dynamiclib 
-o ../../../../lib/mlt/libmltcore.js 
factory.o producer_colour.o producer_consumer.o producer_hold.o producer_loader.o producer_melt.o producer_noise.o producer_timewarp.o producer_tone.o filter_audiochannels.o filter_audiomap.o filter_audioconvert.o filter_audiowave.o filter_brightness.o filter_channelcopy.o filter_crop.o filter_data_feed.o filter_data_show.o filter_fieldorder.o filter_gamma.o filter_greyscale.o filter_imageconvert.o filter_luma.o filter_mirror.o filter_mono.o filter_obscure.o filter_panner.o filter_region.o filter_rescale.o filter_resize.o filter_transition.o filter_watermark.o transition_composite.o transition_luma.o transition_mix.o transition_region.o transition_matte.o consumer_multi.o consumer_null.o 
-L../../framework -lmlt -lm -lpthread

litmltsdl2:

emcc -g -s EXPORT_ALL=1 -s SIDE_MODULE=1 -s WASM=0 -dynamiclib 
-o ../../../../lib/mlt/libmltsdl2.js 
factory.o common.o consumer_sdl2.o consumer_sdl2_audio.o 
-L../../framework -lmlt -lpthread -lm -s USE_SDL=2

最后是我的可执行文件:

emcc -g -s SAFE_HEAP=1 -s WASM=0 -s TOTAL_MEMORY=1024MB -s EXIT_RUNTIME=1 -s EXPORT_ALL=1 -s MAIN_MODULE=1 
-O2 -I$(pwd)/dist/include/mlt $(pwd)/dist/lib/libmlt.bc 
--preload-file lib/mlt 
--preload-file lib/share 
melt.c -o melt.html --pre-js melt_pre.js

我尝试过各种其他标志:

ALIASING_FUNCTION_POINTERS=0
SAFE_HEAP=1
STACK_OVERFLOW_CHECK=1
EMULATE_FUNCTION_POINTER_CASTS=1 
ASSERTIONS=2

-g4 看起来可能会有帮助,但在构建库时无法找到源文件。

最佳答案

值得一看at the full list and descriptions of emcc compiler options 。阅读链接中的说明后,您将意识到您提到的所有其他标志对您的情况没有帮助。

首先,我很确定您不能对 -s TOTAL_MEMORY= 标志使用 MB 表示法,因为正如您在上面看到的, -s 标志实际上是 JavaScript。尝试使用普通整数代替。另外 -s ALLOW_MEMORY_GROWTH=1 会让堆根据需要自动增长。

请注意,pthread 在某些浏览器中默认不可用,因为它(准确地说是 SharedArrayBuffer)受到 Meltdown 漏洞的影响,因此在浏览器中被禁用。

关于c - 如何调试由于超出可用动态堆而导致的 Emscripten 段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55583474/

相关文章:

c - '*' token 之前的语法错误

javascript - 将 Emscripten 与 Fortran 一起使用 : LAPACK binding

javascript - 将 JS ArrayBuffer 或 TypedArray 传递给 Emscripten,无需复制

c++ - ivec4 作为顶点属性 Opengl ES 2.0

C ncurses 阻止调整大小

c - OpenWrt SDK自定义包 'make'失败,因为缺少libpthread.so.0

c - 从文件中解析 http 响应

c - 超过缓冲区大小?

firefox - 如何从 C 代码生成带有 i64 而不是 i32 的 Webassembly (WAT)

llvm - 如何使 emcc 工作?