elixir/erlang 堆栈跟踪。正确的函数调用解释

问题描述 投票:0回答:1

如何解释

FunctionClauseError

中的函数属性
 %FunctionClauseError{
   module: MyApp.MyModule,
   function: :"-load_data/4-inlined-0-",
   arity: 1,
   kind: nil,
   args: nil,
   clauses: nil
}

术语

-load_data/4-inlined-0-
指向
load_data/4
函数内部的某些内容。
这部分怎么解释:
inlined-0

我假设它指向
load_data/4
函数体中的第一个宏调用。
这部分环境似乎没有记录。谁能详细解释一下这个问题?

erlang elixir trace
1个回答
1
投票

当编译器内联匿名函数时,会出现

-load_data/4-inlined-0-
函数名,并且对匿名函数的调用失败并出现函数子句错误。它不是实际函数的名称;添加它是为了解决这个问题,标题为“令人困惑的
case_clause
异常而不是
function_clause
”。我不认为这在任何地方都有记录。


这需要一点历史课。让我们考虑一下这段代码:

-module(foo).

-export([foo/0]).

foo() ->
    F = fun(X) when is_atom(X) -> ok end,
    F(0).

也就是说,我们创建一个匿名函数,然后我们以导致函数子句错误的方式调用它。

匿名函数的内联是在 Erlang/OTP 24 中引入的。因此,当在 Erlang 23 中运行时,我们可以看到堆栈跟踪中的函数名称是匿名函数的常用名称,带有

-fun-
:

> catch foo:foo().
{'EXIT',{function_clause,[{foo,'-foo/0-fun-0-',
                               [0],
                               [{file,"foo.erl"},{line,6}]},
                          {erl_eval,do_apply,6,[{file,"erl_eval.erl"},{line,684}]},
                          {erl_eval,expr,5,[{file,"erl_eval.erl"},{line,437}]},
                          {shell,exprs,7,[{file,"shell.erl"},{line,686}]},
                          {shell,eval_exprs,7,[{file,"shell.erl"},{line,642}]},
                          {shell,eval_loop,3,[{file,"shell.erl"},{line,627}]}]}}

在 Erlang 24 中,该函数由编译器内联,并重写为

case
表达式。因此,我们看到一个
case_clause
异常,并且堆栈跟踪表明错误发生在
foo
函数本身:

> catch foo:foo().
{'EXIT',{{case_clause,{0}},
         [{foo,foo,0,[{file,"foo.erl"},{line,6}]},
          {erl_eval,do_apply,6,[{file,"erl_eval.erl"},{line,689}]},
          {erl_eval,expr,5,[{file,"erl_eval.erl"},{line,434}]},
          {shell,exprs,7,[{file,"shell.erl"},{line,686}]},
          {shell,eval_exprs,7,[{file,"shell.erl"},{line,642}]},
          {shell,eval_loop,3,[{file,"shell.erl"},{line,627}]}]}}

当然,对于寻找

case
表达式来查找错误原因的程序员来说,这很令人困惑,但没有找到任何原因。这就是为什么 Erlang 25 确保使用实际的
function_clause
异常,以反映错误发生在代码中有函数调用的地方这一事实。它使用
-inlined-
而不是
-fun-
,因为编译后的模块中不再存在匿名函数:

> catch foo:foo().
{'EXIT',{function_clause,[{foo,'-foo/0-inlined-0-',
                               [0],
                               [{file,"foo.erl"},{line,6}]},
                          {erl_eval,do_apply,7,[{file,"erl_eval.erl"},{line,748}]},
                          {erl_eval,expr,6,[{file,"erl_eval.erl"},{line,480}]},
                          {shell,exprs,7,[{file,"shell.erl"},{line,691}]},
                          {shell,eval_exprs,7,[{file,"shell.erl"},{line,647}]},
                          {shell,eval_loop,3,[{file,"shell.erl"},{line,632}]}]}}
© www.soinside.com 2019 - 2024. All rights reserved.