2011-01-30 27 views
7

Đôi khi các lỗi có thể gây ra ngoại lệ vi phạm truy cập bộ nhớ.Chính xác ngoại lệ vi phạm truy cập được kích hoạt

Chính xác ngoại lệ này được kích hoạt như thế nào? Cơ chế nào hoạt động sau hậu trường?

Liệu nó cần sự hỗ trợ từ CPU (bắt đầu từ những gì CPU?)/Từ hệ điều hành (bắt đầu từ phiên bản nào?)/Từ trình biên dịch (bắt đầu từ phiên bản nào?)

Edit:

Một kịch bản cụ thể mà tôi muốn hiểu rõ hơn:

Mã sau có thể gây ra ngoại lệ vi phạm truy cập.

TCHAR* czXXX= _T("ABCDEFG"); 
czXXX[0]= 'A'; 

Tôi đoán czXXX trỏ tới khối bộ nhớ chỉ đọc, nhưng chính xác thì điều gì xảy ra?

Trả lời

11

vi phạm truy cập bộ nhớ là một chủ đề lớn :)

The Protection of Information in Computer Systems (từ năm 1973 :) đưa ra một cơ chế của đoạn, nơi quá trình được phân bổ cơ sở ràng buộc; bất kỳ nỗ lực nào để truy cập bộ nhớ ngoài phạm vi base:base+bound có nghĩa là chương trình đã làm điều gì đó ngớ ngẩn và nên bị giết.

Bộ xử lý 80x86 thực hiện hỗ trợ phân đoạn cơ bản và hạt nhân bảo mật GEMSOS là hạt nhân hệ điều hành được chứng nhận A1 dựa trên cơ chế này.

Nhưng phân khúc không phải là rất năng động và hầu hết các hệ điều hành hiện đại là paging hệ thống, có trang trong bộ nhớ khi không có sẵn. Điều này dựa trên CPU có một đơn vị quản lý bộ nhớ MMU, kiểm tra tất cả các truy cập bộ nhớ cho các đặc quyền và sự hiện diện/vắng mặt của bản đồ bộ nhớ chính xác. Khi một quá trình cố gắng truy cập bộ nhớ hiện không được ánh xạ vào RAM, MMU báo hiệu CPU rằng lỗi đã xảy ra và CPU tạm ngưng quá trình tải trang bộ nhớ được yêu cầu từ đĩa. (Hoặc, nếu bộ nhớ không nên được ánh xạ cho quá trình, nói rằng nó cố gắng truy cập 0x0 hoặc một số vị trí bộ nhớ ngẫu nhiên chưa được ánh xạ với mmap hoặc bộ nhớ tương tự phân bổ nguyên thủy, nó giết chết quá trình.)

Intel's 80386 là chip Intel đầu tiên hỗ trợ phân trang, đó là lý do tại sao "386 Enchanced Mode" của Windows 3.1 là vì vậy tốt hơn nhiều so với chế độ 286.

Trình biên dịch không thực sự tham gia, nhưng CPU, MMU và hệ điều hành kernel phải tất cả hoạt động cùng nhau.

+0

nếu RAM và Đĩa đầy đủ thì sao? –

+0

@Scott 混合 理论 nó là bình thường đối với RAM được đầy đủ, hoặc gần như đầy đủ - RAM không sử dụng là lãng phí RAM. Do hiệu suất giảm đi nên máy tính phải sử dụng không gian hoán đổi, thông thường mọi người sẽ cố gắng chỉ chạy nhiều phần mềm như sẽ phù hợp với bộ nhớ. Khi không gian hoán đổi đã đầy, hạt nhân sẽ bắt đầu trả về lỗi cho cấp phát bộ nhớ hoặc sẽ giết toàn bộ các quy trình để giải phóng dung lượng. Hãy tìm "OOM Killer" để biết chi tiết về điều đó. – sarnold

0
void Kaboom() 
{ 
    int* certain_death = NULL; 
    *certain_death = 0; 
} 
+1

Thực tế ví dụ của bạn có hành vi không xác định theo tiêu chuẩn;) – undercover

6

Trong kiến ​​trúc x86 (và hầu hết mọi thứ khác nữa), điều này được bắt đầu từ MMU - Bộ phận quản lý bộ nhớ. MMU được sử dụng để dịch các địa chỉ bộ nhớ ảo thành địa chỉ bộ nhớ vật lý. Nếu một yêu cầu được thực hiện để truy cập một địa chỉ không hợp lệ (0x00000000 hoặc một cái gì đó quá cao) thì MMU sẽ bẫy (ngắt) tới hệ điều hành (điều này thực tế được thực hiện cho mọi truy cập không có trong bộ nhớ đệm dịch ")). Ở đây hệ điều hành có thể nói rằng đây là một truy cập bộ nhớ bất hợp pháp, và tuyên truyền cho ứng dụng người dùng thông qua cơ chế phụ thuộc vào hệ điều hành (các tín hiệu trong Linux (SIGSEGV), tôi không quen với Windows đủ để nói nó được thực hiện như thế nào trong đó).

Tính năng này khả dụng cho mọi CPU, hệ điều hành và trình biên dịch hiện đại. Yêu cầu cơ bản nhất là một MMU, có mặt trong tất cả trừ các CPU nhúng cơ bản nhất. Tôi nghi ngờ có bất kỳ PC hiện đang hoạt động mà không hỗ trợ này.

Edit:

Tiếp theo OP chỉnh sửa, khi một chuỗi chữ được sử dụng, bộ nhớ được đặt trong phân khúc .text của thực thi. Đây là nơi mã nhị phân và giá trị không đổi ngồi. Đương nhiên, trong hầu hết các hệ điều hành này là chỉ đọc (đặc biệt là dưới Linux với các cải tiến bảo mật khác nhau). Khi bạn cố gắng thay đổi một giá trị của một chuỗi chữ, bạn về cơ bản đang cố gắng ghi vào bộ nhớ chỉ đọc, gây ra một sự vi phạm truy cập. Một lần nữa, điều này được bắt gặp bởi MMU mà thấy một lệnh ghi vào một địa chỉ bộ nhớ chỉ đọc.

+1

Cơ chế phụ thuộc vào hệ điều hành được gọi là "ngoại lệ có cấu trúc" trong Windows: http://msdn.microsoft.com/en-us/library/ms680657%28v=vs .85% 29.aspx – sbk

2

Khi bạn cố gắng truy cập vào một địa chỉ bộ nhớ, máy tính đi qua một vài bước:

  • Nếu địa chỉ là một phần của phân đoạn bộ nhớ hiện tại, truy cập được cấp.
  • Nếu không, nếu phân đoạn của địa chỉ nằm trong bộ nhớ có quyền truy cập thích hợp, quyền truy cập được cấp.

Nếu địa chỉ không có trong bộ nhớ, CPU sẽ tạo ngoại lệ kiểm tra bộ nhớ. Tại thời điểm này, hệ điều hành đã kết thúc.

  • Nếu phân khúc này hiện có sẵn trong bộ nhớ ảo với sự cho phép truy cập thích hợp, nó được nạp vào bộ nhớ và giao cho người quản lý bộ nhớ ảo; truy cập sau đó được cấp.

Nếu, tại thời điểm này, bộ nhớ không khả dụng, có một trong hai khả năng. Địa chỉ không có sẵn hoặc bạn không có quyền bạn cần (ví dụ: cố gắng ghi vào bộ nhớ chỉ đọc). Trong trường hợp này, hệ điều hành sẽ vượt qua vi phạm quyền truy cập vào quy trình.

Đối với các phiên bản CPU và OS, đây là bất kỳ hệ thống nào cho phép bộ nhớ ảo. Tôi không biết chi tiết về điều này.

1

Memory vi phạm truy cập có thể xảy ra ở đây cũng:

delete pSample; 

//again deleting the same memory! 
delete pSample; 

Đối với trường hợp này, ngoại lệ được huy động từ các mô hình bộ nhớ của hệ điều hành. Chủ yếu là hệ điều hành mà công việc của họ là xác thực truy cập bộ nhớ từ bất kỳ quá trình nào!

2

Tất cả các câu trả lời này giải thích điều gì xảy ra ở cấp độ bộ xử lý rất tốt. Như đã đề cập, một khi bộ vi xử lý tăng đột biến cho hệ điều hành, thì mọi thứ thay đổi với các hệ điều hành khác nhau.

Windows sử dụng cơ chế được gọi là "Structured exceptions". Rất quan trọng không nhầm lẫn điều này với ngoại lệ C++, chúng khác nhau. Ngoại lệ có cấu trúc khái niệm hoạt động theo cùng cách với ngoại lệ C++, trong đó chúng giải phóng ngăn xếp tìm kiếm trình xử lý. Vì Ngoại lệ có cấu trúc là thuyết bất khả tri về ngôn ngữ, chúng thực hiện không trình hủy cuộc gọi hoặc thực hiện bất kỳ việc dọn dẹp nào.

Exceptions có cấu trúc có thể được bắt gặp với

__try 
{ 
    //Usual code 
} 
__except(EXCEPTION_EXECUTE_HANDLER) 
{ 
    //Handling code 
} 
__finally 
{ 
    //Cleanup 
} 

Được cảnh báo tuy nhiên, một khi bạn có được một ngoại lệ có cấu trúc, chương trình của bạn có đã bị rơi, vì vậy không có cách lành mạnh để 'phục hồi'.

Thông tin thêm về SEH.

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