2009-05-15 33 views
10

Tại sao trình biên dịch Erlang không phát hiện các hàm không xác định trong thời gian biên dịch.Tại sao erlang: foo() biên dịch?

Nếu tôi viết test.erl:

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

start() -> 
     erlang:foo(). 

Nó biên dịch tốt.

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

Nhưng thời gian chạy bị treo.

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

Tại sao trình biên dịch không đưa ra lỗi hoặc cảnh báo về điều này trong khi biên dịch? Nó nên biết về chức năng xuất khẩu, phải không?

Trả lời

16

Erlang là ngôn ngữ động. Tuy nhiên, thực hành tốt là thực hiện kiểm tra loại và phân tích tĩnh sau khi biên dịch.

Công cụ Dialyzer được sử dụng để kiểm tra loại lỗi này.

Lý do trình biên dịch không biết về thời gian biên dịch là vì các hàm có thể được tìm kiếm và được nạp động từ đường dẫn mã tại thời gian chạy (và cũng từ nút từ xa). Dialyzer sẽ kiểm tra mã trên đường dẫn mã tại thời điểm nó được chạy.

Khả năng tải mã từ nút từ xa có nghĩa là 'hệ thống' cơ bản có thể được cài đặt trên thiết bị và sau đó thiết bị có thể tự khởi động từ mạng.

Bạn cũng nên nhớ một đặc tính của Erlang mà bạn có thể tạo ra chức năng gọi on the fly sử dụng các cấu trúc như:

erlang:apply(ModuleName, FunctionName, ArgList) 

như vậy trong trường hợp đó nó chỉ đơn giản là không thể biết nếu chức năng tồn tại thời gian biên dịch hay không .

Và mặc dù mô-đun và chức năng có thể tồn tại lúc biên dịch, bạn có thể hoán đổi các mô-đun nóng và dỡ mã, vì vậy nó có thể không có ở thời gian chạy.

+1

Không chỉ đường dẫn mã mà còn các nút khác trong cụm Erlang.Mã không phải là cục bộ để được nạp vào một máy ảo Erlang và được thực thi. –

+1

Tôi đã không thực sự nghĩ về điều đó. Một cái nhìn nhanh chóng tại Cookbook Erlang lần lượt lên làm thế nào để làm điều đó. http://www.trapexit.org/Remote_Code_Load –

+0

Ngoài ra, bạn được tự do thay thế hoặc dỡ bỏ mô-đun trong thời gian chạy, vì vậy ngay cả khi trình biên dịch đã kiểm tra ngay bây giờ, nó vẫn có thể bị lỗi sau. – archaelus

0

Tôi nghĩ rằng đây là câu hỏi triển khai khi các nhà phát triển Erlang quyết định kết nối thời gian chạy thay vì liên kết xây dựng. Một phần lý do có thể có gì đó để làm phiên bản và/hoặc tải mã động.

0

Bạn có thể sử dụng ứng dụng xref để kiểm tra việc sử dụng các chức năng không dùng nữa, không được xác định và không sử dụng (và hơn thế nữa!).

Biên soạn các mô-đun với debug_info:

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

Kiểm tra các mô-đun với xref:m/1:

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

Bạn có thể muốn kiểm tra thêm về xref đây:

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

Erlang -- xref (Tools Reference Manual)

Các vấn đề liên quan