2015-06-07 16 views
10

Cẩn thận với việc sử dụng lệnh Exit trong các hàm nội dòng! Tôi đã sử dụng Delphi XE3 ở đây.Có phải là lỗi cố gắng biên dịch mã này dẫn đến kết thúc IDE hoặc trình biên dịch không chạy?

Triệu chứng

Trong một số trường hợp, khi một cuộc gọi được thực hiện để một hàm nội tuyến có chứa Exit lệnh, và sự trở lại giá trị của hàm inline được sử dụng trực tiếp trong WriteLn(), trình biên dịch báo cáo một lỗi tin nhắn,

"dcc" exited with code 1.

hoặc thậm chí tệ nhất, IDE Delphi chấm dứt mà không có bất kỳ xác nhận nào.

function ProcessNumber(const iNumber: Integer): Boolean; inline; 
begin 
    if iNumber = 0 then begin 
    Result := False; 
    Exit; 
    end; 
    // some code here ... 
    Result := True; 
end; 

procedure Test; 
begin 
    writeln(ProcessNumber(0)); 
end; 

begin 
    Test; 
    ReadLn; 
end. 

Tuy nhiên, nếu giá trị trả về của hàm inline được lưu trữ trong một biến, và sau đó biến được sử dụng trong WriteLn(), vấn đề không xảy ra.

procedure Test; 
var 
    b: Boolean; 
begin 
    b := ProcessNumber(0); 
    writeln(b); 
end; 

Câu hỏi

  1. Đây có phải là một lỗi biên dịch?
  2. Nếu lỗi này, có cách nào khác để thoát khỏi một hàm an toàn không?
+0

Nó làm cho tôi tự hỏi, anh có hy vọng điều này để thoát khỏi bối cảnh người gọi, hay chỉ là chức năng inline? – TLama

+0

@TLama Tôi nghĩ người hỏi biết rằng 'inline' không thay đổi' lối ra' nghĩa là gì.Đó là AV nội bộ giết chết IDE đó là vấn đề. –

Trả lời

10

Đây chắc chắn là lỗi. Nó xảy ra trong tất cả các phiên bản IDE mà tôi đã thử nghiệm, XE3, XE7 và XE8. Tôi thành thật không nghĩ rằng có rất nhiều bạn có thể làm. Đối với tôi, IDE chấm dứt trên trình biên dịch mỗi lần. Tôi nghĩ bạn sẽ phải viết mã theo cách không dẫn đến sự cố IDE.

Bạn có thể sử dụng tùy chọn IDE để buộc biên dịch sử dụng msbuild. Điều này đặt trình biên dịch thành một quá trình riêng biệt và do đó đảm bảo rằng IDE sẽ không bị lỗi. Nó sẽ không giúp bạn nhiều mặc dù bởi vì mặc dù IDE của bạn sẽ không tiếp tục chết, bạn vẫn sẽ không thể biên dịch chương trình của bạn!

Khi bạn xây dựng với msbuild, bạn nhận được một lỗi của mẫu này:

error F2084: Internal Error: GPFC00000FD-004D3F34-0

Các GPF là viết tắt của chung Protection Fault, đó là một vi phạm truy cập bộ nhớ. Điều này có lẽ là một ngoại lệ chưa được giải quyết đang giết chết IDE khi quá trình biên dịch được thực hiện trong tiến trình.

Lời khuyên của tôi là bạn gửi báo cáo lỗi đến Quality Portal. Đó là cách duy nhất để khắc phục lỗi. Mặc dù không mong đợi một sửa chữa bao giờ đến với XE3.

+0

Heffernan, cảm ơn câu trả lời. Tôi đã gửi [lỗi] (https://quality.embarcadero.com/browse/AP-165) đến Cổng thông tin chất lượng. Tôi nghĩ rằng, tôi buộc phải sử dụng 'goto' * labelExit * làm giải pháp cho bây giờ. – Astaroth

+0

@Astaroth - thoát ra không phải luôn luôn là một vấn đề. Điều này có vẻ tốt f.i: Kết quả: = iNumber <> 0; nếu không thì kết quả thì thoát; ... –

2

Một cách giải quyết khác mà bạn có thể sử dụng ở đây là đảo ngược nếu triển khai có điều kiện và do đó tránh sử dụng lệnh Thoát hoàn toàn.

Vì vậy, thay vì sử dụng

function ProcessNumber(const iNumber: Integer): Boolean; inline; 
begin 
    if iNumber = 0 then begin 
    Result := False; 
    Exit; 
    end; 
    // some code here ... 
    Result := True; 
end; 

sử dụng

function ProcessNumber(const iNumber: Integer): Boolean; inline; 
begin 
    if iNumber <> 0 then begin 
    // some code here 
    Result := True; 
    end; 
    else 
    Result := False; 
    //No exit needed here as this is already at the end of your method 
end; 
+1

SilverWarior, tôi đánh giá cao nhận xét của bạn, vì vậy +1 từ tôi. Tuy nhiên, trong ví dụ của tôi, tôi chỉ cho thấy rằng lệnh 'Exit' hoạt động bất ngờ trong một hoàn cảnh nhất định. Ví dụ của tôi không thực sự phản ánh cấu trúc mã thực của tôi. Tôi chắc rằng mọi nhà phát triển đã từng đối mặt với một tình huống mà 'Thoát 'ngay lập tức từ một hàm là lựa chọn tốt nhất có sẵn về mặt hiệu quả. Dù sao, tôi đồng ý với bạn rằng đôi khi (như trong ví dụ của tôi) tránh lệnh 'Exit' không làm giảm hiệu suất mã. – Astaroth

+0

Tôi đã nghi ngờ rằng giải pháp không thể dễ dàng như vậy nhưng bạn vẫn sẽ không tin bao nhiêu lần bạn có thể bỏ qua ngay cả các giải pháp đơn giản nhất. Đặc biệt là khi bạn dành thời gian đập đầu về giải quyết một số vấn đề và quên đi và nhìn vào bức tranh lớn và cố gắng tránh được vấn đề đó ngay từ đầu. – SilverWarior

+0

@Silver Mã thực có thể lớn hơn và tránh thoát sẽ làm cho hàm kém rõ ràng hơn. –

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