为什么erlang:foo()编译?

时间:2009-05-15 19:02:41

标签: erlang

为什么Erlang编译器在编译时没有检测到未定义的函数。

如果我写test.erl:

-module(test). 
-export([start/0]).

start() ->
       erlang:foo().

编译好。

Eshell V5.6.5  (abort with ^G)
1> c(test).
{ok,test}
2> 

但崩溃运行时。

2> test:start().
** exception error: undefined function erlang:foo/0

为什么编译器在编译期间没有发出错误或警告?它应该知道导出的函数,不应该吗?

3 个答案:

答案 0 :(得分:17)

Erlang是一种动态语言。然而,最好进行类型检查和静态分析后编译

工具Dialyzer用于检查此类错误情况。

编译器在编译时不知道它的原因是因为可以在运行时(以及从远程节点)从代码路径中搜索和动态加载函数。透析器将在运行时根据代码路径检查代码。

从远程节点加载代码的能力意味着可以在设备上安装基本的“系统”,然后设备可以从网络引导自己。

你还应该记住Erlang的另一个特性是你可以使用如下结构生成函数调用on the fly

erlang:apply(ModuleName, FunctionName, ArgList)

所以在这种情况下,根本不可能知道函数是否在编译时存在。

虽然模块和函数现在可能在编译时存在,但您可以热插拔模块并卸载代码,因此在运行时可能不存在。

答案 1 :(得分:0)

我认为这是一个实现问题,因为Erlang开发人员决定运行时链接而不是构建时链接。部分原因可能是版本控制和/或动态代码加载。

答案 2 :(得分:0)

您可以使用xref应用程序检查已弃用,未定义和未使用的函数的使用情况(以及更多!)。

使用debug_info编译模块:

Eshell V6.2  (abort with ^G)
1> c(test, debug_info).
{ok,test}

使用xref:m/1检查模块:

2> xref:m(test).
[{deprecated,[]},
 {undefined,[{{test,start,0},{erlang,foo,0}}]},
 {unused,[]}]

您可以在此处查看有关xref的更多信息:

Erlang -- Xref - The Cross Reference Tool (Tools User's Guide)

Erlang -- xref (Tools Reference Manual)