Bạn có xử lý các điều kiện hết bộ nhớ không?


9

Bạn làm gì khi malloctrả về 0 hoặc ném ngoại lệ mới? Chỉ cần dừng lại hoặc cố gắng sống sót trong điều kiện OOM / lưu công việc của người dùng?


4
Liên quan đến Stackoverflow stackoverflow.com/questions/763159/ từ
ysolik

11
Argh. Tôi tiếp tục đọc điều này là "hết mana". Quá nhiều trò chơi video trong quá khứ của tôi, tôi nghĩ. :)
Adam Lear

Câu trả lời:


4

Tôi sẽ tránh OOM như tránh một vụ tai nạn.

Tránh làm một khối lượng lớn công việc (và phân bổ khối lượng lớn bộ nhớ) cùng một lúc. Giữ dữ liệu trên đĩa, tin tưởng vào bộ đệm đĩa hệ điều hành và sử dụng IO ánh xạ bộ nhớ càng nhiều càng tốt và chỉ hoạt động trên một phần nhỏ dữ liệu tại một thời điểm. Nếu một lượng lớn dữ liệu cần phải được thực hiện trực tuyến (được phục vụ với độ trễ thấp) thì hãy giữ chúng trong bộ nhớ trên một số máy, giống như tất cả các công ty công cụ tìm kiếm lớn làm. Hoặc mua SSD.


Rõ ràng điều này có ý nghĩa nhất.
mbq

2
Có một cuộc tranh luận lớn về cách xử lý OOM một cách duyên dáng (RAII, an toàn ngoại lệ, blah ...) nhưng một khi tôi nhận ra rằng trong một hệ thống đa luồng có nhiều mô-đun động (một số từ bên thứ ba), ngay cả khi luồng của bạn không sụp đổ, có một thời điểm không may trong đó mọi chủ đề sẽ thấy một OOM. Nếu thậm chí một người quyết định đi trước, bạn không thể làm gì khác ngoài việc tận mắt chứng kiến.
rwong

13

Hầu hết mọi người trả lời câu hỏi này có lẽ chưa bao giờ làm việc trên các hệ thống nhúng, trong đó malloc trả về 0 là một khả năng rất thực tế. Trên một hệ thống tôi hiện đang làm việc, có tổng cộng 4,25K byte RAM (đó là 4352 byte). Tôi đang phân bổ 64 byte cho ngăn xếp và hiện có một đống 1600 byte. Mới hôm qua tôi đã gỡ lỗi một thói quen đi bộ heap để tôi có thể làm theo sự phân bổ và giải phóng bộ nhớ. Heap walk sử dụng bộ đệm được phân bổ tĩnh (30 byte) nhỏ để xuất ra cổng nối tiếp. Nó sẽ bị tắt cho phiên bản phát hành.

Vì đây là một sản phẩm tiêu dùng, tốt hơn hết là không hết bộ nhớ một khi sản phẩm đã được phát hành. Tôi chắc chắn rằng nó sẽ trong quá trình phát triển. Trong mọi trường hợp, về tất cả những gì tôi có thể làm là phát ra tiếng bíp cho người nói một vài lần và buộc khởi động lại.


2
Các chức năng phù hợp bên trong một không gian nhỏ thật đáng kinh ngạc ... đó là một hình thức nghệ thuật như cây cảnh
rwong

6
Nhiều dự án trên các hệ thống nhúng chỉ đơn giản là cấm phân bổ bộ nhớ động. Trường hợp duy nhất của OOM vẫn là chồng tràn.
mouviciel

Bạn đúng, nhưng đặc biệt với câu đầu tiên của bạn: hầu hết điều này đơn giản là không phù hợp với hầu hết các nhà phát triển.
Konrad Rudolph

4

Thành thật mà nói, trong tất cả các dự án tôi đã thực hiện (hãy nhớ rằng tôi chưa làm việc ở bất cứ đâu), tôi chưa bao giờ nghĩ rằng điều đó có thể xảy ra, và do đó tôi cho rằng các chương trình của tôi sẽ chết rất nhanh.

Bên cạnh đó, việc xử lý một OOM đòi hỏi bạn phải phân bổ các tài nguyên để hiển thị thông báo lỗi hoặc lưu tất cả mọi thứ, điều này có thể gây bất tiện.

Tôi cảm thấy rằng những ngày này, bộ nhớ có giá thấp hơn đậu phộng, đó không phải là điều nên xảy ra thường xuyên. Vào buổi bình minh của ký ức được bảo vệ và trước đây, có lẽ đó là một mối quan tâm, nhưng bây giờ thì sao? Các lỗi OOM duy nhất tôi từng thấy là từ mã lỗi.


Tôi có thể nghĩ đến việc lấy lại một số bộ nhớ mà quá trình đã có và cố gắng sống sót và phục hồi (khó nếu bạn vứt bỏ bất cứ thứ gì hữu ích) hoặc để tồn tại dưới dạng dữ liệu + tàn dư cố gắng lưu nó.
mbq

2

Kiểm tra mã trả lại malloc dù sao cũng vô nghĩa.

Các hệ điều hành hiện đại vượt quá bộ nhớ: Chúng cung cấp cho các tiến trình nhiều bộ nhớ hơn thực tế có sẵn. Bộ nhớ mà quá trình của bạn được cấp là ảo, tất cả được ánh xạ tới một trang không có trang.

Mãi cho đến khi bạn ghi vào bộ nhớ rằng một trang vật lý, duy nhất được phân bổ cho các quy trình của bạn. Nếu sự phân bổ này không thành công, kernel sẽ chấm dứt một tiến trình (có lẽ là của bạn!) Trong nỗ lực tìm kiếm bộ nhớ. Tại thời điểm đó, bạn không thể làm gì hơn nữa.


Tôi đã có một ý tưởng để vào trong vòng lặp với giấc ngủ dài bên trong - và có thể phục hồi nếu quá trình đó sẽ sống sót sau kẻ giết người OOM. Tôi có một ấn tượng rằng các quy trình đã bị chấm dứt do cố gắng sử dụng địa chỉ 0, nhưng tôi chưa thực hiện bất kỳ thử nghiệm vững chắc nào.
mbq

Bạn không cần phải làm gì đặc biệt để đối phó với kẻ giết người OOM. Nếu quy trình của bạn kích hoạt nó nhưng không được chọn, nó sẽ không bao giờ biết. Mọi thứ sẽ chỉ hoạt động như thể có đủ bộ nhớ. Nếu mặt khác, quy trình của bạn được chọn, nó sẽ bị chấm dứt và bạn cũng không thể làm gì được.
Kristof Provost

Nhưng tôi có thể cố gắng đợi OOM giải phóng một số bộ nhớ và sau đó cố gắng phân bổ lại và tiếp tục. Tôi có một ấn tượng rằng malloc / new không chờ đợi điều này xảy ra.
mbq

Không, bạn không thể. Phân bổ của bạn sẽ luôn luôn thành công. Bạn sẽ nhận được tất cả bộ nhớ ảo mà bạn muốn. Chỉ đến khi bạn chạm vào nó, bộ nhớ vật lý mới được phân bổ. Ngay khi bạn chạm vào một trang chưa được phân bổ, quy trình của bạn sẽ bị treo. Hạt nhân sẽ tìm kiếm thêm bộ nhớ, điều này có thể khiến nó giết chết một quá trình để có thêm bộ nhớ. Nếu điều đó thành công (và nó không giết chết bạn!), Trang sẽ được phân bổ và quy trình của bạn sẽ tiếp tục. Không có cách nào để quá trình của bạn nói rằng điều này đã xảy ra.
Kristof Provost

2
Tôi khá chắc chắn rằng các cửa sổ không bao giờ thừa. Nó có thể cam kết nhiều hơn RAM, nhưng không nhiều hơn RAM + hoán đổi.
CodeInChaos

2

Trừ khi bạn đang phát triển cho các hệ thống nhúng, hệ thống thời gian thực hoặc hệ thống nghiêm trọng đến mức các sự cố có thể phải trả giá, hoặc hàng tỷ đô la ... thì có lẽ không đáng để lo lắng về điều kiện bộ nhớ.

Trong hầu hết các trường hợp, có rất ít việc có thể được thực hiện khi bạn hết bộ nhớ, vì không có bộ nhớ để tạo bất kỳ đối tượng mới nào hoặc thực hiện bất kỳ tác vụ nào có thể làm gì đó. Bạn phải cân nhắc chi phí của ứng dụng xử lý OOM so với lợi ích bạn nhận được từ việc đó.


Các hệ thống thời gian thực không cần kiểm tra nhiều hơn về lỗi malloc so với các hệ thống khác.
zneak

@zneak - Không đúng sự thật. Các hệ thống thời gian thực phải có thể dự đoán được và hết bộ nhớ là không thể dự đoán được trừ khi bạn có kế hoạch cụ thể cho nó.
Erik Funkenbusch

Vì vậy, bạn sẽ làm gì hơn nữa khi bạn nhấn OOM?
zneak

Bộ nhớ trống, hủy quá trình, v.v. Một hệ thống thời gian thực thường không có bộ nhớ ảo hoặc hệ thống trao đổi vì nó phải có tính xác định. Vì vậy, nó có thể dễ dàng hết bộ nhớ hơn.
Erik Funkenbusch

Đưa ra một đường dẫn mã nhất định chắc chắn sẽ dẫn đến lỗi OOM, tôi không thấy sự cố là cách tiếp cận ít xác định hơn giải phóng bộ nhớ và hủy bỏ các quy trình.
zneak

1

Tôi sẽ luôn luôn kiểm tra lỗi. Nếu một cái gì đó trả về một điều kiện lỗi, thì nó phải được xử lý bởi chương trình của bạn. Ngay cả khi đó là một thông báo có nội dung "Hết bộ nhớ, bạn phải đi!", Nó vẫn tốt hơn "Vi phạm truy cập", "đổ lõi" hoặc bất cứ điều gì. Một là một điều kiện lỗi bạn xử lý, hai là một lỗi. Và người dùng sẽ cảm nhận nó như vậy là tốt.

Đối với trường hợp cụ thể của bạn, bạn có thể cố gắng khôi phục hoạt động, giải phóng các tài nguyên mà bạn đã phân bổ cho đến khi gặp sự cố, báo cáo lỗi và tiếp tục thực hiện (có thể khi bạn đang cố thoát khỏi ứng dụng, bạn có thể cung cấp cho tùy chọn để thoát ngay lập tức). Bằng cách này, người dùng có thể quyết định phải làm gì hoặc cố gắng giải phóng bộ nhớ bằng cách xử lý xung quanh, đóng tệp, v.v ... Tất nhiên, cách bạn có thể xử lý tình huống phụ thuộc nhiều vào chương trình của bạn - một chương trình không được cho là có thể tương tác có lẽ chỉ cần ghi lại lỗi và thoát hoặc tiếp tụ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.