2010-02-12 8 views
24

Đó là thực tế chung để kiểm tra NULL (cho dù bộ nhớ được phân bổ thành công) sau một malloc(), một số điều nhưCó một nhu cầu để kiểm tra NULL sau khi phân bổ bộ nhớ, khi hạt nhân sử dụng bộ nhớ overcommit

void *ptr = malloc(10);  
if (ptr != NULL) { 
    // do some thing usefull 
} else { 
// no memory. safely return/throw ... 
} 

với overcommit bộ nhớ được kích hoạt trong hạt nhân, là có một cơ hội nhận được NULL? Tôi có nên thực hiện theo các thực hành kiểm tra tôn giáo NULL cho mỗi phân bổ? Liệu malloc trả về NULL có khơi gợi cơ chế overcommit tăng cường (tôi đoán giá trị 1)?

Như một vấn đề của thực tế hạt nhân Android sử dụng overcommit bộ nhớ (không chắc chắn về giá trị, rất thích biết nó (overcommit giá trị) và ý nghĩa của nó). Một số mã nguồn khung (C/C++) trong Android (có thể là bên thứ 3) không kiểm tra NULL cũng như không nhận được bad_alloc sau khi phân bổ. Tui bỏ lỡ điều gì vậy?

Có một số chủ đề trong SO liên quan đến bộ nhớ quá mức, nhưng không có chủ đề nào trong số đó giải quyết được sự nhầm lẫn của tôi.

CHỈNH SỬA: Nếu quá mức vượt quá đang được sử dụng NULL sẽ không được trả về (giả định 1). Khi không có bộ nhớ vật lý có sẵn và trên cố gắng truy cập vào bộ nhớ được cấp phát (ghi vào bộ nhớ được phân bổ), OOM sẽ giết một số tiến trình và cấp phát bộ nhớ cho ứng dụng cho đến khi nó bị giết lần lượt (giả định 2). Trong cả hai trường hợp tôi không thấy bất kỳ nhu cầu cho cheking NULL (bộ nhớ nhận được phân bổ hoặc quá trình nhận được giết chết). Tôi có đúng trong các giả định của tôi không?
Tính di động không phải là mối quan ngại cho câu hỏi này.

+0

* bộ nhớ quá mức * là gì? Nếu bạn đang nói về một tệp trang trên thiết bị thì KHÔNG, Android (và các thiết bị di động khác) thường không sử dụng tệp trang. Đó là bởi vì việc viết sẽ làm hao mòn bộ nhớ NAND hoặc Flash của SSD sớm hơn. Hay bạn đang nói về mô phỏng và hypervisors? – jww

Trả lời

34

Có, bạn vẫn nên kiểm tra lỗi do malloc trả lại. Trong môi trường quá mức bộ nhớ, bạn sẽ không thể phát hiện và khôi phục từ thất bại do môi trường hết bộ nhớ vật lý cần thiết khi bạn ghi vào các phần của không gian địa chỉ đã được cấp phát cho chương trình của bạn bằng cuộc gọi trước tới malloc.

Tuy nhiên, đây không phải là vấn đề duy nhất khiến malloc thất bại trong môi trường truyền thống.Yêu cầu cho một khối bộ nhớ đặc biệt lớn khi không gian địa chỉ của chương trình của bạn bị phân mảnh có thể bị lỗi ngay cả khi có đủ bộ nhớ vật lý đủ khả năng để đáp ứng yêu cầu. Vì không có không gian địa chỉ miễn phí liền kề malloc phải không thành công. Loại lỗi này phải được báo hiệu bằng cách malloc trả lại NULL, cho dù môi trường có quá mức bộ nhớ hay không.

+5

+1 để chỉ ra 'phân mảnh'. – FL4SOF

+0

Nếu bạn cố gắng phân bổ 1M bộ nhớ và malloc trả về NULL do phân mảnh như thế nào để bạn tiến hành xử lý trường hợp này? Điều gì sẽ xảy ra nếu bạn cố gắng phân bổ rất nhiều bộ nhớ do lỗi, không phải bạn sẽ gặp sự cố và có được một kết xuất cốt lõi hơn là thoát ra hoặc làm việc xung quanh lỗi? – Skrymsli

+0

@Skrymsli: Nó phụ thuộc vào ứng dụng và môi trường. Nếu "crashing" ngay lập tức là bắt buộc sau đó tôi muốn một 'abort' rõ ràng hơn là thực hiện chạy một khoảng thời gian không xác định cho đến khi một số sử dụng con trỏ null gây ra một vụ tai nạn như là một tác dụng phụ. Một số ứng dụng có thể lọc rất nhiều bộ nhớ được cấp phát và khôi phục theo một cách nào đó. Tuy nhiên, tiền đề của câu hỏi là tôi nên kiểm tra null bởi vì, chắc chắn, với quá cam kết nó sẽ không bao giờ xảy ra mà tôi yêu cầu là không đúng sự thật. –

8

Bạn phải kiểm tra giá trị trả lại cho NULL mỗi lần. Bất kỳ chức năng thư viện nào đều có thể bị lỗi. Ngay cả fclose() làm (trên chia sẻ NFS bị ngắt kết nối, và lỗi từ fclose của tệp NFS có nghĩa là, dữ liệu đó không được lưu).

Phần lớn phần mềm được viết kém và không chứa tất cả các kiểm tra.

malloc không thể trả lại thứ gì khác ngoài NULL hoặc con trỏ. Tất cả hoặc không có gì. Bạn không thể nhận được 1 byte từ malloc nếu bạn yêu cầu 10.

+0

câu hỏi của tôi không phải là với việc thực hiện malloc, nhưng sử dụng malloc. với overcommit bộ nhớ được kích hoạt, có rất ít cơ hội nhận được NULL (về mặt lý thuyết) và nó là hiển nhiên trong một số các nguồn khung android c/C++ - mà không làm kiểm tra này sau khi phân bổ. – FL4SOF

+0

Với quá tải mallic sẽ thất bại xa hơn. http://opsmonkey.blogspot.com/2007/01/linux-memory-overcommit.html Nói chung, malloc sẽ không thất bại, khi bộ nhớ có sẵn và ulimit không đạt được – osgx

+0

"Với malloc thừa sẽ thất bại xa hơn." Tôi tin rằng đây là giả định sai, hãy nhìn vào liên kết bạn đã đề cập. Nó nói demo1: bộ nhớ malloc và không sử dụng nó: Phân bổ 1,4TB, bị sát hại bởi kẻ giết người OOM demo2: bộ nhớ malloc và sử dụng nó ngay lập tức: Phân bổ 7.8GB, bị sát hại bởi kẻ sát nhân OOM (quá trình bị sát hại bởi OOM killer chứ không phải một trường hợp của malloc thất bại). – FL4SOF

2

Bạn nên kiểm tra NULL một cách tôn giáo trên tất cả các cuộc gọi hàm có thể trả về NULL, bất kể hạt nhân có bộ nhớ quá mức hay không.

này sau đoạn mã dưới đây cho thấy làm thế nào để kiểm tra xem các cuộc gọi đến malloc làm việc hay không ... hoạt động

 
void *ptr = malloc(10); 
if (ptr != NULL){ 
    /* Do something here with ptr */ 
}else{ 
    /* Do something here if it fails */ 
} 

File, hoạt động bộ nhớ để tên nhưng một vài sẽ trả về một NULL khi thất bại.

Hy vọng điều này sẽ giúp, Trân trọng, Tom.

+0

'phân đoạn mã là một giả định nguy hiểm' bạn có thể giải thích? 'Thiết bị trung gian Android' xin lỗi vì đã quá chung chung, 'một số mã nguồn công việc khung (C/C++) trong android' tôi nên nói. Tôi sẽ chỉnh sửa câu hỏi của mình. – FL4SOF

+0

@ FL4SOF: Vui lòng xem câu trả lời đã chỉnh sửa ... – t0mm13b

+0

Có thể đây là chủ đề, nhưng tôi tò mò bạn sẽ làm gì trong/* Làm điều gì đó ở đây nếu nó thất bại */phần? Có lẽ, bất cứ điều gì bạn làm sẽ không thể cấp phát bộ nhớ nếu bạn thực sự không thể phân bổ 10 byte bộ nhớ. Bạn có thể nhận được vào một vòng lặp vô hạn kiểm tra ra khỏi bộ nhớ và xử lý nó .. Bạn chỉ cần thoát khỏi? Đó có phải là tốt hơn so với đâm vào null-dereference bằng cách nào đó? – Skrymsli

-4

Không, không cần phải kiểm tra kết quả của malloc.

Dài trước khi malloc bị lỗi, hệ điều hành đã gặp phải rất nhiều sự cố.

+3

Câu trả lời của bạn là câu trả lời không liên quan. Tôi gỡ bỏ một nửa của nó. Ngoài ra câu trả lời của bạn là xấu, vì vậy tôi đã bỏ phiếu nó xuống. – kay

+0

Tôi không biết tại sao trang web này cho phép bạn chỉnh sửa bài đăng của mình. Nhưng với OOM-Killer và bộ nhớ Overcommit, kiểm tra con trỏ null sau khi malloc không còn cần thiết và trở nên gây hiểu nhầm. – Shaoquan

+0

Vui lòng xem http://stackoverflow.com/faq#editing.Bạn có thể hoàn tác các thay đổi của tôi cũng như… Đối với câu hỏi ban đầu: đúng là các hệ điều hành hiện đại phân bổ RAM cho quá trình lười biếng và quá tải. Và khi bộ nhớ thực sự được truy cập, nó sẽ được cấp phát. Và có lẽ ai đó đã có được OOM'd chỉ sau đó. Nhưng đó không phải là câu hỏi. malloc gọi brk để tăng heap háo hức. Hệ điều hành của tôi từ chối yêu cầu. Trong trường hợp này malloc sẽ trả về NULL. Ví dụ. ulimit có thể giới hạn kích thước bộ nhớ ảo tối đa của quá trình được đề cập. – kay