Đang tải... (xem toàn văn)
Thông tin tài liệu
Ngày đăng: 03/04/2016, 20:35
Từ khóa liên quan
Mục lục
Trong chương này quản lý bộ nhớ đối với ngôn ngữ cấu trúc khối sẽ được mô tả bằng cấu trúc dữ liệu thời gian thực mà được sử dụng trong cài đặt tham chiếu đơn giản. Các đặc trưng của ngôn ngữ lập trình mà tạo nên liên kết giữa các tên trong chương trình với các vị trí bộ nhớ quan tâm là phạm vi, mà cho phép hai tên cú pháp khác nhau tham chiếu đến hai vị trí khác nhau, và các lời gọi hàm, mà mỗi lời gọi yêu cầu một vùng nhớ mới ở đó lưu trữ các tham số của hàm và các biến cục bộ. Một số chủ đề quan trọng trong chương này là truyền tham số, truy cập biến tổng thể và tối ưu bộ nhớ gắn kết với kiểu gọi hàm chuyên biệt gọi là tail call. Chúng ta sẽ thấy quản lý bộ nhớ trở nên phức tạp trong các ngôn ngữ có các khai báo hàm lồng nhau mà cho phép hàm được truyền như các tham số hoặc trả về như kết quả của lời gọi hàm.
2.1. Ngôn ngữ cấu trúc khối
Trong đoạn code này có hai khối. Mỗi khối bắt đầu bằng mở ngoặc trái { và kết thúc bằng đóng ngoặc phải }. Khối ngoài được bắt đầu bằng mở ngoặc móc thứ nhất và đóng ngoặc móc phải sau cùng. Khối trong được lồng trong khối ngoài. Nó bắt đầu bằng mở ngoặc móc thứ hai và đóng ngoặc móc phải thứ nhất. Biến x được khai báo trong block ngoài và biến y trong block trong. Một biến được khai báo bên trong một block được coi là cục bộ đối với block đó. Một biến được khai báo trong một block bao bọc một block đang xét được coi là tổng thể của block bên trong đó. Trong ví dụ này, x là cục bộ đối với block ngoài, y là cục bộ đối với block trong và x là tổng thể đối với block trong.
C, Pascal, ML là các ngôn ngữ cấu trúc khối. Các khối được xác định bởi {…} trong C, begin … end trong Pascal và let…in…end trong ML. Thân của các thủ tục hoặc hàm cũng là các khối trong các ngôn ngữ lập trình đó.
Cơ chế quản lý bộ nhớ liên kết với cấu trúc khối cho phép các hàm được gọi đệ qui.
Các phiên bản Fortran được sử dụng rộng rãi trong những năm 1960 và 1970 không là cấu trúc khối. Trong Fortran kinh điển, mỗi biến bao gồm các tham số của mỗi thủ tục (được gọi là subroutine trong Fortran) được gán với một vị trí bộ nhớ cố định. Điều đó làm cho không thể gọi thủ tục đệ qui, hoặc trực tiếp hoặc gián tiếp. Nếu trong Fortran, procedure P gọi Q và Q gọi R và sau đó R thử gọi P, thì lần gọi P thứ hai là không cho phép. Giả sử P được gọi lần hai, thì trong chuỗi gọi đó, lần gọi hai sẽ ghi đè lên các tham số và địa chỉ trả về của lần gọi thứ nhất. Điều này làm cho nó không thể gọi để trả về kết quả một cách đúng đắn.
Các ngôn ngữ cấu trúc khối được đặc trưng bởi các tính chất sau:
Các biến mới có thể được khai báo ở các vị trí khác nhau trong chương trình
Mỗi khai báo được nhìn thấy bên trong một vùng nào đó của chương trình được gọi là block. Block có thể lồng nhau, nhưng không được chồng cắt nhau từng phần. Nói cách khác, hai block chứa một biểu thức hoặc các lệnh chung nào đó, thì một block sẽ chứa chọn vẹn trong block kia.
Khi chương trình bắt đầu thực hiện các chỉ lệnh chứa trong một block trong thời gian thực, bộ nhớ được cấp cho các biến được khai báo trong block.
Khi chương trình thoát ra khỏi block, một số hoặc toàn bộ bộ nhớ cấp cho các biến khai báo trong block được thu hồi.
Định danh mà không khai báo trong block hiện thời được coi là tổng thể đối với block và được tham chiếu đến thực thể có tên đó được khai báo trong block bao bọc gần nhất.
Có vẻ ngạc nhiên là hầu hết các phức tạp liên quan đến việc truy cập các biến tổng thể. Tuy nhiên, điều này trên thực tế là kết quả của việc quản lý bộ nhớ dựa trên ngăn xếp. Ngăn xếp được sử dụng làm cho dễ dàng cấp và truy cập các biến cục bộ. Trong khi các biến cục bộ được đặt gần, thì các biến tổng thể được cất trong ngăn xếp dưới một số bản ghi kích hoạt.
Mô hình máy tính đơn giản
Chúng ta sử dụng mô hình máy tính đơn giản trên Hình sau để xem xét việc quản trị bộ nhớ trong các ngôn ngữ cấu trúc khối.
Mô hình máy trên Hình 4.1 tách bộ nhớ code khỏi bộ nhớ dữ liệu. Bộ đếm chương trình lưu trữ địa chỉ của chỉ lệnh hiện tại của chương trình và được tăng một cách bình thường sau mỗi chỉ lệnh. Khi chương trình vào một block mới, một bản ghi kích hoạt activation record chứa bộ nhớ cho các biến cục bộ khai báo trong block được bổ sung thêm vào ngăn xếp thời gian chạy (run-time stack – được vẽ trên đỉnh bộ nhớ dữ liệu), và con trỏ môi trường được thiết lập đến bản ghi mới này. Khi chương trình thoát khỏi khối, bản ghi kích hoạt đó được xóa khỏi ngăn xếp và con trỏ môi trường sẽ được đặt lại vị trí cũ. Chương trình có thể lưu lại dữ liệu, mà có thể tồn tại lâu hơn sau khi thực hiện khối hiện thời, trên đống heap. Trên thực tế, bản ghi kích hoạt được cấp mới nhất là cái đầu tiên sẽ bị thu hồi, thường được gọi là stack discipline. Mặc dù hầu hết các ngôn ngữ cấu trúc khối được cài đặt bởi ngăn xếp, các hàm bậc cao có thể làm cho stack discipline bị lỗi.
Tuy Hình 4.1 có một số thanh ghi, nói chung được dùng để lưu trữ địa chỉ và dữ liệu trong thời gian ngắn, chúng ta sẽ không bàn đến thanh ghi hoặc chỉ lệnh mà có thể lưu trữ trên đoạn code của bộ nhớ.
Cài đặt tham chiếu. Cài đặt tham chiếu là cài đặt ngôn ngữ mà được thiết kế để xác định hành vi của ngôn ngữ. Nó không cần phải là cài đặt hiệu quả. Mục đích của chương này là cho bạn thông tin về việc các khối được cài đặt như thế nào trong hầu hết các ngôn ngữ lập trình để bạn có thể hiểu khi nào bộ nhớ cần được cấp phát, kiểu dữ liệu nào được lưu trữ trên ngăn xếp thời gian chạy, làm thế nào để chương trình đang thực hiện truy cập đến các bộ nhớ dữ liệu khi cần thiết. Chúng ta sẽ làm điều đó bằng cách mô tả cài đặt tham chiếu. Vì mục đích của chúng ta là hiểu chương trình chứ không phải xây dựng chương trình dịch, chương trình tham chiếu này sẽ đơn giản và trực tiếp. Các phương pháp hiệu quả hơn để làm nhiều việc mà được mô tả trong chương này, tùy thuộc vào các ngôn ngữ cụ thể, có thể tìm trong các cuốn sách về chương trình dịch.
Ghi chú về C.
Ngôn ngữ lập trình C được thiết kế làm cho C dễ dịch và dễ thực hiện, tránh một số kỹ thuật phạm vi tổng quát và quản trị bộ nhớ mô tả trong chương này. Hiểu các trường hợp tổng quát xét ở đây sẽ cho các lập trình viên C hiểu một số cách mà ở đó C đơn giản hơn các ngôn ngữ khác. Thêm vào đó, các lập trình viên C, người mà muốn hiệu quả trong việc truyền hàm và môi trường của nó cho hàm khác, có thể sử dụng ý tưởng được mô tả trong chương này cho chương trình của họ.
Tài liệu cùng người dùng
Tài liệu liên quan