Có bất kỳ trường hợp sửa đổi mã thời gian chạy thông minh nào không?


119

Bạn có thể nghĩ về bất kỳ cách sử dụng hợp pháp (thông minh) nào để sửa đổi mã thời gian chạy (chương trình sửa đổi mã của chính nó trong thời gian chạy) không?

Các hệ điều hành hiện đại dường như không thích các chương trình làm điều này vì kỹ thuật này đã được sử dụng bởi vi rút để tránh bị phát hiện.

Tất cả những gì tôi có thể nghĩ đến là một số loại tối ưu hóa thời gian chạy sẽ loại bỏ hoặc thêm một số mã bằng cách biết điều gì đó trong thời gian chạy mà không thể biết được vào thời gian biên dịch.


8
Trên các kiến ​​trúc hiện đại, nó can thiệp rất nhiều vào bộ nhớ đệm và đường dẫn hướng dẫn: mã tự sửa đổi sẽ không sửa đổi bộ đệm, vì vậy bạn sẽ cần các rào cản và điều này có thể làm cho mã của bạn chậm đi. Và bạn không thể sửa đổi mã đã có trong đường dẫn hướng dẫn. Vì vậy, bất kỳ tối ưu hóa nào dựa trên mã tự sửa đổi phải được thực hiện theo cách trước khi mã được chạy để có tác động hiệu suất vượt trội hơn, chẳng hạn như kiểm tra thời gian chạy.
Alexandre C.

7
@Alexandre: thông thường mã tự sửa đổi để thực hiện các sửa đổi hiếm khi thay đổi (ví dụ: một lần, hai lần) mặc dù được thực thi một số lần tùy ý, vì vậy chi phí một lần có thể không đáng kể.
Tony Delroy

7
Không chắc tại sao điều này được gắn thẻ C hoặc C ++, vì cả hai đều không có bất kỳ cơ chế nào cho việc này.
MSalters

4
@Alexandre: Microsoft Office được biết là làm chính xác điều đó. Kết quả là (?) Tất cả các bộ xử lý x86 đều có hỗ trợ tuyệt vời cho việc tự sửa đổi mã. Trên các bộ xử lý khác, đồng bộ hóa tốn kém là cần thiết, điều này làm cho toàn bộ điều này kém hấp dẫn hơn.
Mackie Messer

3
@Cawas: Thông thường, phần mềm tự động cập nhật sẽ tải xuống các tập hợp và / hoặc tệp thực thi mới và ghi đè lên các cụm hiện có. Sau đó, nó sẽ khởi động lại phần mềm. Đây là những gì firefox, adobe, v.v. làm. Tự sửa đổi thường có nghĩa là trong thời gian chạy, mã được ứng dụng ghi lại trong bộ nhớ do một số tham số và không nhất thiết phải quay trở lại đĩa. Ví dụ: nó có thể tối ưu hóa toàn bộ đường dẫn mã nếu nó có thể phát hiện một cách thông minh những đường dẫn đó sẽ không được thực hiện trong quá trình chạy cụ thể này để tăng tốc độ thực thi.
NotMe

Câu trả lời:


117

Có nhiều trường hợp hợp lệ để sửa đổi mã. Tạo mã trong thời gian chạy có thể hữu ích cho:

  • Một số máy ảo sử dụng biên dịch JIT để cải thiện hiệu suất.
  • Tạo các chức năng chuyên biệt một cách nhanh chóng từ lâu đã trở nên phổ biến trong đồ họa máy tính. Xem ví dụ như Rob Pike và Bart Locanthi và John Reiser Đánh đổi phần mềm phần cứng cho Đồ họa Bitmap trên Blit (1984) hoặc bài đăng này (2006) của Chris Lattner về việc Apple sử dụng LLVM cho chuyên môn hóa mã thời gian chạy trong ngăn xếp OpenGL của họ.
  • Trong một số trường hợp, phần mềm sử dụng một kỹ thuật được gọi là tấm bạt lò xo liên quan đến việc tạo mã động trên ngăn xếp (hoặc một nơi khác). Ví dụ như các chức năng lồng nhau của GCC và cơ chế tín hiệu của một số Unices.

Đôi khi mã được dịch thành mã trong thời gian chạy (đây được gọi là dịch nhị phân động ):

  • Trình giả lập như Rosetta của Apple sử dụng kỹ thuật này để tăng tốc độ giả lập. Một ví dụ khác là phần mềm biến đổi mã của Transmeta .
  • Trình gỡ lỗi và trình định cấu hình phức tạp như Valgrind hoặc Pin sử dụng nó để tạo công cụ cho mã của bạn trong khi nó đang được thực thi.
  • Trước khi các phần mở rộng được tạo cho tập lệnh x86, phần mềm ảo hóa như VMWare không thể chạy trực tiếp mã x86 đặc quyền bên trong các máy ảo. Thay vào đó, nó phải dịch nhanh mọi hướng dẫn có vấn đề thành mã tùy chỉnh thích hợp hơn.

Sửa đổi mã có thể được sử dụng để giải quyết các hạn chế của tập lệnh:

  • Đã có một thời gian (lâu rồi, tôi biết), khi máy tính không có hướng dẫn để quay lại từ một chương trình con hoặc địa chỉ gián tiếp bộ nhớ. Mã tự sửa đổi là cách duy nhất để triển khai các chương trình con, con trỏ và mảng .

Các trường hợp sửa đổi mã khác:

  • Nhiều trình gỡ lỗi thay thế các hướng dẫn để triển khai các điểm ngắt .
  • Một số trình liên kết động sửa đổi mã trong thời gian chạy. Bài viết này cung cấp một số thông tin cơ bản về việc tái định vị thời gian chạy của Windows DLL, đây là một hình thức sửa đổi mã hiệu quả.

10
Danh sách này dường như trộn lẫn các ví dụ về mã tự sửa đổi và mã sửa đổi mã khác, như trình liên kết.
AShelly

6
@AShelly: Chà, nếu bạn coi trình liên kết động / trình tải là một phần của mã, thì nó sẽ tự sửa đổi. Họ sống trong cùng một không gian địa chỉ, vì vậy tôi nghĩ rằng đó là một quan điểm hợp lệ.
Mackie Messer

1
Ok, danh sách bây giờ phân biệt giữa các chương trình và phần mềm hệ thống. Tôi hy vọng điều này có ý nghĩa. Cuối cùng thì bất kỳ phân loại nào cũng gây tranh cãi. Tất cả đều phụ thuộc vào những gì bạn đưa vào định nghĩa chương trình (hoặc mã) một cách chính xác.
Mackie Messer

35

Điều này đã được thực hiện trong đồ họa máy tính, đặc biệt là trình kết xuất phần mềm cho mục đích tối ưu hóa. Trong thời gian chạy, trạng thái của nhiều tham số được kiểm tra và một phiên bản được tối ưu hóa của mã rasterizer được tạo (có khả năng loại bỏ rất nhiều điều kiện) cho phép người ta kết xuất đồ họa gốc, ví dụ như hình tam giác nhanh hơn nhiều.


5
Một bài đọc thú vị là các bài báo 3 phần Pixomatic của Michael Abrash trên DDJ : drdobbs.com/architecture-and-design/184405765 , drdobbs.com/184405807 , drdobbs.com/184405848 . Liên kết thứ hai (Phần 2) nói về thợ hàn mã Pixomatic cho đường ống pixel.
typo.pl

1
Một bài viết rất hay về chủ đề này. Từ năm 1984, nhưng vẫn được đọc tốt: Rob Pike và Bart Locanthi và John Reiser. Đánh đổi phần cứng Phần mềm cho Đồ họa Bitmap trên Blit .
Mackie Messer

5
Charles Petzold giải thích một ví dụ về loại này trong một cuốn sách có tựa đề "Beautiful Code": amazon.com/Beautiful-Code-Leading-Programmers-Practice/dp/…
Nawaz

3
Câu trả lời này nói về việc tạo mã, nhưng câu hỏi đặt ra về việc sửa đổi mã ...
Timwi

3
@Timwi - nó đã sửa đổi mã. Thay vì xử lý một chuỗi lớn if, nó đã phân tích cú pháp hình dạng một lần và viết lại trình kết xuất để nó được thiết lập cho đúng loại hình dạng mà không cần phải kiểm tra mọi lúc. Điều thú vị là điều này hiện phổ biến với mã opencl - vì nó được biên dịch nhanh chóng, bạn có thể viết lại nó cho trường hợp cụ thể trong thời gian chạy
Martin Beckett

23

Một lý do hợp lệ là vì tập lệnh asm thiếu một số hướng dẫn cần thiết mà bạn có thể tự xây dựng . Ví dụ: Trên x86 không có cách nào tạo ngắt cho một biến trong thanh ghi (ví dụ: tạo ngắt với số ngắt trong ax). Chỉ cho phép các số const được mã hóa trong opcode. Với mã tự sửa đổi, người ta có thể mô phỏng hành vi này.


Đủ công bằng. Có cách nào sử dụng kỹ thuật này không? Nó có vẻ nguy hiểm.
Alexandre C.

4
@Alexandre C.: Nếu tôi nhớ đúng thì nhiều thư viện thời gian chạy (C, Pascal, ...) đã phải DOS lần một hàm để thực hiện các cuộc gọi ngắt. Vì các hàm như vậy lấy số ngắt làm tham số mà bạn phải cung cấp cho một hàm như vậy (tất nhiên nếu số không đổi, bạn có thể tạo đúng mã, nhưng điều đó không được đảm bảo). Và tất cả các thư viện đã triển khai nó bằng mã tự sửa đổi.
flolo

Bạn có thể sử dụng trường hợp chuyển đổi để làm điều đó mà không cần sửa đổi mã. Các giảm bớt là các mã đầu ra sẽ lớn hơn
phuclv

17

Một số trình biên dịch đã từng sử dụng nó để khởi tạo biến tĩnh, tránh tốn kém một điều kiện cho các lần truy cập tiếp theo. Nói cách khác, họ thực hiện "thực thi mã này chỉ một lần" bằng cách ghi đè mã đó bằng các lệnh không hoạt động trong lần đầu tiên nó được thực thi.


1
Rất tốt, đặc biệt là nếu nó tránh được khóa / mở khóa mutex.
Tony Delroy

2
Có thật không? Làm thế nào để điều này xảy ra đối với mã dựa trên ROM hoặc đối với mã được thực thi trong đoạn mã được bảo vệ chống ghi?
Ira Baxter

1
@Ira Baxter: bất kỳ trình biên dịch nào phát ra mã định vị lại đều biết rằng đoạn mã có thể ghi được, ít nhất là trong khi khởi động. Vì vậy, tuyên bố "một số trình biên dịch đã sử dụng nó" vẫn có thể.
MSalters

17

Có nhiều trường hợp:

  • Vi rút thường sử dụng mã tự sửa đổi để "giải mã" mã của chúng trước khi thực thi, nhưng kỹ thuật đó cũng có thể hữu ích trong việc phá hủy kỹ thuật ngược, bẻ khóa và hack không mong muốn
  • Trong một số trường hợp, có thể có một điểm cụ thể trong thời gian chạy (ví dụ ngay sau khi đọc tệp cấu hình) khi biết rằng - trong suốt thời gian còn lại của quá trình - một nhánh cụ thể sẽ luôn hoặc không bao giờ được sử dụng: thay vì không cần thiết kiểm tra một số biến để xác định cách rẽ nhánh, bản thân lệnh rẽ nhánh có thể được sửa đổi cho phù hợp
    • ví dụ: Có thể biết rằng chỉ một trong các kiểu dẫn xuất có thể được xử lý, như vậy có thể thay thế công văn ảo bằng một lệnh gọi cụ thể
    • Sau khi phát hiện phần cứng nào khả dụng, việc sử dụng mã phù hợp có thể được mã hóa cứng
  • Mã không cần thiết có thể được thay thế bằng hướng dẫn no-op hoặc nhảy qua nó hoặc chuyển bit mã tiếp theo trực tiếp vào vị trí (dễ dàng hơn nếu sử dụng mã opcodes độc lập vị trí)
  • Mã được viết để tạo điều kiện cho việc gỡ lỗi của chính nó có thể đưa vào một lệnh bẫy / tín hiệu / ngắt mà trình gỡ lỗi mong đợi tại một vị trí chiến lược.
  • Một số biểu thức vị từ dựa trên đầu vào của người dùng có thể được thư viện biên dịch thành mã gốc
  • Nội tuyến một số hoạt động đơn giản không hiển thị cho đến thời gian chạy (ví dụ: từ thư viện được tải động) ...
  • Có điều kiện thêm các bước tự đo đạc / lập hồ sơ
  • Các vết nứt có thể được thực hiện dưới dạng thư viện sửa đổi mã tải chúng (không phải "tự" sửa đổi chính xác, nhưng cần các kỹ thuật và quyền tương tự).
  • ...

Một số mô hình bảo mật của hệ điều hành có nghĩa là mã tự sửa đổi không thể chạy nếu không có đặc quyền root / admin, khiến nó không thực tế cho mục đích sử dụng chung.

Từ Wikipedia:

Phần mềm ứng dụng chạy trong hệ điều hành có bảo mật W ^ X nghiêm ngặt không thể thực thi các hướng dẫn trong các trang mà nó được phép ghi vào — chỉ bản thân hệ điều hành mới được phép ghi các lệnh vào bộ nhớ và sau đó thực thi các lệnh đó.

Trên các hệ điều hành như vậy, ngay cả các chương trình như máy ảo Java cũng cần có quyền root / admin để thực thi mã JIT của chúng. (Xem http://en.wikipedia.org/wiki/W%5EX để biết thêm chi tiết)


2
Bạn không cần đặc quyền root để tự sửa đổi mã. Java VM cũng vậy.
Mackie Messer

Tôi không biết một số hệ điều hành nghiêm ngặt như vậy. Nhưng nó chắc chắn có ý nghĩa trong một số ứng dụng. Tôi làm ngạc nhiên tuy nhiên nếu thực hiện Java với quyền root không thực sự tăng cường an ninh ...
Mackie Messer

@Mackie: Tôi nghĩ nó phải giảm nó, nhưng có lẽ nó có thể thiết lập một số quyền bộ nhớ sau đó thay đổi uid có hiệu lực trở lại một số tài khoản người dùng ...?
Tony Delroy

Có, tôi mong đợi họ có một cơ chế chi tiết để cấp quyền đi kèm với mô hình bảo mật nghiêm ngặt.
Mackie Messer

15

Các Tổng hợp hệ điều hành cơ bản phần đánh giá chương trình của bạn đối với các cuộc gọi API với, và thay thế hệ điều hành mã với kết quả. Lợi ích chính là rất nhiều kiểm tra lỗi đã biến mất (bởi vì nếu chương trình của bạn không yêu cầu hệ điều hành làm điều gì đó ngu ngốc, nó không cần phải kiểm tra).

Vâng, đó là một ví dụ về tối ưu hóa thời gian chạy.


Tôi không nhìn thấy điểm. Nếu nói rằng một cuộc gọi hệ thống sẽ bị hệ điều hành cấm, bạn có thể sẽ nhận được lỗi mà bạn sẽ phải kiểm tra mã, phải không? Đối với tôi, có vẻ như việc sửa đổi tệp thực thi thay vì trả lại mã lỗi là một cách khai thác quá mức.
Alexandre C.

@Alexandre C.: bạn có thể loại bỏ kiểm tra con trỏ rỗng theo cách đó. Thường thì đối với người gọi, một đối số là hợp lệ là điều hiển nhiên.
MSalters

@Alexandre: Bạn có thể đọc nghiên cứu tại liên kết. Tôi nghĩ rằng họ có tốc độ khá ấn tượng, và đó sẽ là vấn đề: -}
Ira Baxter

2
Đối với các cuộc gọi tổng hợp tương đối nhỏ và không ràng buộc I / O, khoản tiết kiệm được là đáng kể. Ví dụ: nếu bạn đang viết một lệnh dừng cho Unix, bạn sẽ thực hiện một loạt các cuộc gọi bảng mã nồi hơi để ngắt kết nối stdio, thiết lập các bộ xử lý tín hiệu khác nhau, v.v. Nếu bạn biết rằng các tham số của cuộc gọi là hằng số và kết quả sẽ luôn giống nhau (ví dụ: đóng stdin), rất nhiều mã bạn thực thi trong trường hợp chung là không cần thiết.
Mark Bessey

1
Nếu bạn đọc luận án, chương 8 chứa một số con số thực sự ấn tượng về I / O thời gian thực không nhỏ để thu thập dữ liệu. Nhớ rằng đây là một luận án giữa những năm 1980, và chiếc máy anh ấy đang chạy là 10? Mhz 68000, anh ấy đã có thể nắm bắt được dữ liệu âm thanh chất lượng CD (44.000 mẫu một giây) bằng phần mềm cũ đơn giản. Ông tuyên bố rằng các máy trạm Sun (Unix cổ điển) chỉ có thể đạt khoảng 1/5 tỷ lệ đó. Tôi là một lập trình viên hợp ngữ cũ từ những ngày đó, và điều này khá ngoạn mục.
Ira Baxter

9

Nhiều năm trước, tôi đã dành một buổi sáng để gỡ lỗi một số mã tự sửa đổi, một lệnh đã thay đổi địa chỉ đích của lệnh sau, tức là, tôi đang tính toán một địa chỉ chi nhánh. Nó được viết bằng hợp ngữ và hoạt động hoàn hảo khi tôi thực hiện từng bước một trong chương trình. Nhưng khi tôi chạy chương trình, nó không thành công. Cuối cùng, tôi nhận ra rằng máy đang tìm nạp 2 lệnh từ bộ nhớ và (như các lệnh đã được trình bày trong bộ nhớ) lệnh mà tôi đang sửa đổi đã được tìm nạp và do đó máy đang thực hiện phiên bản không sửa đổi (không chính xác) của lệnh. Tất nhiên, khi tôi đang gỡ lỗi, nó chỉ thực hiện một lệnh tại một thời điểm.

Quan điểm của tôi, mã tự sửa đổi có thể cực kỳ khó kiểm tra / gỡ lỗi và thường có các giả định ẩn về hoạt động của máy (có thể là phần cứng hoặc ảo). Hơn nữa, hệ thống không bao giờ có thể chia sẻ các trang mã giữa các luồng / quy trình khác nhau đang thực thi trên các máy đa lõi (hiện nay). Điều này làm mất đi nhiều lợi ích đối với bộ nhớ ảo, v.v. Nó cũng sẽ làm mất hiệu lực tối ưu hóa nhánh được thực hiện ở cấp phần cứng.

(Lưu ý - tôi không đưa JIT vào danh mục mã tự sửa đổi. JIT đang dịch từ một biểu diễn mã sang biểu diễn thay thế, nó không sửa đổi mã)

Nói chung, đó chỉ là một ý tưởng tồi - thực sự gọn gàng, thực sự tối nghĩa, nhưng thực sự tệ.

tất nhiên - nếu tất cả những gì bạn có là 8080 và ~ 512 byte bộ nhớ, bạn có thể phải sử dụng các phương pháp như vậy.


1
Tôi không biết, tốt và xấu dường như không phải là phạm trù thích hợp để nghĩ về điều này. Tất nhiên bạn phải thực sự biết những gì bạn đang làm và lý do tại sao bạn đang làm điều đó. Nhưng lập trình viên viết mã đó có lẽ không muốn bạn thấy chương trình đang làm gì. Tất nhiên thật khó chịu nếu bạn phải gỡ lỗi mã như vậy. Nhưng mã đó rất có thể có ý nghĩa như vậy.
Mackie Messer

Các CPU x86 hiện đại có khả năng phát hiện SMC mạnh hơn so với yêu cầu trên giấy: Quan sát tìm nạp lệnh cũ trên x86 với mã tự sửa đổi . Và trên hầu hết các CPU không phải x86 (như ARM), bộ đệm chỉ dẫn không nhất quán với bộ đệm dữ liệu, vì vậy cần phải xả / đồng bộ thủ công trước khi các byte mới được lưu trữ có thể được thực thi một cách đáng tin cậy như hướng dẫn. Community.arm.com/processors/b/blog/posts/… . Dù bằng cách nào, hiệu suất SMC rất khủng khiếp trên các CPU hiện đại, trừ khi bạn sửa đổi một lần và chạy nhiều lần.
Peter Cordes

7

Từ quan điểm của một nhân hệ điều hành, mọi Trình biên dịch Chỉ Trong Thời gian và Thời gian chạy Trình liên kết thực hiện tự sửa đổi văn bản chương trình. Ví dụ nổi bật là Trình thông dịch tập lệnh V8 ECMA của Google.


5

Một lý do khác của việc mã tự sửa đổi (thực ra là mã "tự tạo") là để triển khai cơ chế biên dịch Just-In-time cho hiệu suất. Ví dụ: một chương trình đọc một biểu thức algectures và tính toán nó trên một loạt các tham số đầu vào có thể chuyển đổi biểu thức trong mã máy trước khi nêu phép tính.


5

Bạn biết đấy, không có sự khác biệt hợp lý giữa phần cứng và phần mềm ... người ta cũng có thể nói rằng không có sự khác biệt hợp lý giữa mã và dữ liệu.

Mã tự sửa đổi là gì? Mã đặt các giá trị trong luồng thực thi để nó có thể được diễn giải không phải là dữ liệu mà là một lệnh. Chắc chắn có quan điểm lý thuyết trong ngôn ngữ chức năng rằng thực sự không có sự khác biệt. Tôi đang nói trên e có thể làm điều này một cách đơn giản bằng các ngôn ngữ mệnh lệnh và trình biên dịch / thông dịch viên mà không cần giả định về tình trạng bình đẳng.

Những gì tôi đang đề cập đến là theo nghĩa thực tế, dữ liệu có thể thay đổi đường dẫn thực thi chương trình (theo nghĩa nào đó, điều này cực kỳ rõ ràng). Tôi đang nghĩ đến thứ gì đó giống như trình biên dịch-trình biên dịch tạo ra một bảng (một mảng dữ liệu) mà người ta duyệt qua trong phân tích cú pháp, chuyển từ trạng thái này sang trạng thái khác (và cũng sửa đổi các biến khác), giống như cách một chương trình chuyển từ lệnh sang lệnh , sửa đổi các biến trong quy trình.

Vì vậy, ngay cả trong trường hợp thông thường khi trình biên dịch tạo không gian mã và tham chiếu đến không gian dữ liệu hoàn toàn riêng biệt (đống), người ta vẫn có thể sửa đổi dữ liệu để thay đổi rõ ràng đường dẫn thực thi.


4
Không có sự khác biệt logic, đúng. Tuy nhiên, chưa thấy quá nhiều mạch tích hợp tự sửa đổi.
Ira Baxter

@Mitch, IMO thay đổi đường dẫn thực thi không liên quan gì đến việc sửa đổi (tự) mã. Bên cạnh đó, bạn nhầm lẫn dữ liệu với thông tin. Tôi không thể trả lời bình luận của năm cho câu trả lời của tôi trong LSE b / c Tôi bị cấm ở đó, kể từ tháng 2, trong 3 năm (1.000 ngày) vì thể hiện trong meta-LSE bài viết của tôi rằng người Mỹ và người Anh không sở hữu tiếng Anh.
Gennady Vanin Геннадий Ванин

4

Tôi đã triển khai một chương trình sử dụng sự tiến hóa để tạo ra thuật toán tốt nhất. Nó sử dụng mã tự sửa đổi để sửa đổi bản thiết kế DNA.


2

Một trường hợp sử dụng là tệp kiểm tra EICAR là tệp COM thực thi DOS hợp pháp để kiểm tra các chương trình chống vi-rút.

X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*

Nó phải sử dụng tự sửa đổi mã vì tệp thực thi chỉ được chứa các ký tự ASCII có thể in / đánh máy trong phạm vi [21h-60h, 7Bh-7Dh], điều này giới hạn đáng kể số lượng lệnh có thể mã hóa

Chi tiết được giải thích tại đây


Nó cũng được sử dụng để điều phối hoạt động dấu phẩy động trong DOS

Một số trình biên dịch sẽ phát ra CD xxvới xx nằm trong khoảng từ 0x34-0x3B ở vị trí của các lệnh dấu phẩy động x87. Vì CDlà mã lựa chọn cho intlệnh, nó sẽ nhảy vào ngắt 34h-3Bh và mô phỏng lệnh đó trong phần mềm nếu bộ đồng xử lý x87 không khả dụng. Nếu không, trình xử lý ngắt sẽ thay thế 2 byte đó bằng 9B Dxđể các lần thực thi sau này sẽ được x87 xử lý trực tiếp mà không cần mô phỏng.

Giao thức mô phỏng dấu chấm động x87 trong MS-DOS là gì?


1

Nhân Linux có các mô-đun nhân có thể tải được để thực hiện điều đó.

Emacs cũng có khả năng này và tôi sử dụng nó mọi lúc.

Bất kỳ thứ gì hỗ trợ kiến ​​trúc plugin động về cơ bản là sửa đổi mã của nó trong thời gian chạy.


4
khó khăn. có một thư viện có thể tải động mà không phải lúc nào cũng thường trú, rất ít liên quan đến mã tự sửa đổi.
Dov

1

Tôi chạy các phân tích thống kê dựa trên cơ sở dữ liệu được cập nhật liên tục. Mô hình thống kê của tôi được viết và viết lại mỗi khi mã được thực thi để phù hợp với dữ liệu mới có sẵn.


0

Kịch bản mà điều này có thể được sử dụng là một chương trình học tập. Để phản hồi lại đầu vào của người dùng, chương trình học một thuật toán mới:

  1. nó tìm kiếm cơ sở mã hiện có cho một thuật toán tương tự
  2. nếu không có thuật toán tương tự trong cơ sở mã, chương trình chỉ thêm một thuật toán mới
  3. nếu một thuật toán tương tự tồn tại, chương trình (có thể với một số trợ giúp từ người dùng) sẽ sửa đổi thuật toán hiện có để có thể phục vụ cả mục đích cũ và mục đích mới

Có một câu hỏi làm thế nào để làm điều đó trong Java: Khả năng tự sửa đổi mã Java là gì?


-1

Phiên bản tốt nhất của điều này có thể là Lisp Macro. Không giống như C macro chỉ là một Lisp tiền xử lý cho phép bạn luôn có quyền truy cập vào toàn bộ ngôn ngữ lập trình. Đây là tính năng mạnh nhất trong ngọng và không tồn tại trong bất kỳ ngôn ngữ nào khác.

Tôi không có nghĩa là một chuyên gia nhưng có được một trong những kẻ ngọng nói về nó! Có một lý do mà họ nói rằng Lisp là ngôn ngữ mạnh mẽ nhất xung quanh và những người thông minh không cho rằng họ có thể đúng.


2
Điều đó có thực sự tạo ra mã tự sửa đổi hay chỉ là một bộ tiền xử lý mạnh hơn (một bộ sẽ tạo ra các chức năng)?
Brendan Long

@Brendan: đúng vậy, nhưng đó cách thích hợp để thực hiện tiền xử lý. Không có sửa đổi mã thời gian chạy ở đây.
Alexandre C.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.