MethodError во время выполнения для скомпилированной версии приложения Julia, которая в противном случае работает нормально - PullRequest
2 голосов
/ 25 сентября 2019

У меня есть приложение Julia, которое работает нормально, но я хочу сделать его скомпилированную и более легко распространяемую версию.Насколько я понял, это работа PackageCompiler.

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

fatal: error thrown and no exception handler available.
MethodError(f=typeof(Base.convert)(), args=(Int32, nothing), world=0x00000000000065d9)
rec_backtrace at /home/bli/src/julia/src/stackwalk.c:94
record_backtrace at /home/bli/src/julia/src/task.c:219 [inlined]
jl_throw at /home/bli/src/julia/src/task.c:429
jl_method_error_bare at /home/bli/src/julia/src/gf.c:1606
jl_method_error at /home/bli/src/julia/src/gf.c:1624
jl_apply_generic at /home/bli/src/julia/src/gf.c:2161
julia_main at /home/bli/src/qaf_demux/Julia/QafDemux/bin/qaf_demux_to_compile.jl:12
julia_main at /home/bli/src/qaf_demux/Julia/QafDemux/deps/builddir/qaf_demux.so (unknown line)
main at ./deps/builddir/qaf_demux (unknown line)
__libc_start_main at /build/glibc-LK5gWL/glibc-2.23/csu/../csu/libc-start.c:291
_start at ./deps/builddir/qaf_demux (unknown line)

Что означает MethodError?Какую полезную информацию я могу получить из backtrace?

Вот сценарий deps/build.jl, использованный для его компиляции:

import Pkg
Pkg.add("ArgParse")
Pkg.add("IterTools")
Pkg.add("FASTX")
Pkg.add("CodecZlib")
Pkg.add("REPL")
Pkg.add("PackageCompiler")
using PackageCompiler
build_executable(joinpath(@__DIR__, "../bin/qaf_demux_to_compile.jl"), "qaf_demux", snoopfile=joinpath(@__DIR__, "../bin/snoop.jl"))

snoop.jl вызывает основную функцию моего пакета QafDemuxс некоторой командной строкой test (которая соответствует той, которая использовалась для проверки скомпилированного исполняемого файла):

#!/usr/bin/env julia

push!(LOAD_PATH, abspath(joinpath(@__DIR__, "../src/")))
import QafDemux
const qd = QafDemux

test_args = "-i ../../test_data/TCR_ampli_R1_50k.fastq.gz -o test_run -b GCAGAGATAAGC GCAGAGATGCAC GCAGAGACTCAG GCAGAGAGGAAT GCAGAGACGAGG GCAGAGAAGGAG GCAGAGATGTTG GCAGAGACAACT GCAGAGAGGCTA GCAGAGAGAATG GCAGAGACCAAC GCAGAGAGAGAC -s 3 -m 2 -p 0.1"
qd.main(split(test_args))

qaf_demux_to_compile.jl согласно инструкциям PackageCompiler выглядит следующим образом:

#!/usr/bin/env julia

push!(LOAD_PATH, abspath(joinpath(@__DIR__, "../src/")))
import QafDemux
const qd = QafDemux

Base.@ccallable function julia_main(ARGS::Vector{String})::Cint
    qd.main()
end

Не скомпилированная версия, которая отлично работает, практически идентична:

#!/usr/bin/env julia

push!(LOAD_PATH, abspath(joinpath(@__DIR__, "../src/")))
import QafDemux
const qd = QafDemux

qd.main()

(Перекрестная публикация на более ранней стадии моего расследования в https://discourse.julialang.org/t/understanding-runtime-errors-with-packagecompiler-built-executables/29120/2)

1 Ответ

1 голос
/ 27 сентября 2019

Глядя на трассировку стека, вы видите, что Джулия пытается преобразовать nothing в Int32 в строку:

MethodError(f=typeof(Base.convert)(), args=(Int32, nothing), world=0x00000000000065d9)

Это потому, что ваша функция julia_main явно невернуть что-нибудь, и qd.main также, кажется, ничего не вернуть.При отсутствии явного возвращаемого значения Джулия по умолчанию не возвращает ничего.

Однако в контракте типа вашего метода указано, что julia_main должен вернуть Cint, что наваша система выглядит как Int32.Поэтому Джулия пытается преобразовать то, что julia_main (неявно) возвращает в Int32 - что невозможно!

Чтобы это исправить, вам просто нужно убедиться, что вы возвращаете целое число.Лучше было бы сделать:

Base.@ccallable function julia_main(ARGS::Vector{String})::Cint
    try
        qd.main()
    catch e
        print(stderr, e) # print the error to standard error
        return 1 # in command line tools, a return value of 1 means error
    finally
        return 0 # similarly, a return value of 0 means that the program ran properly
    end
end
...