Lỗi tràn ngăn xếp là gì? Loại chương trình/ngôn ngữ lập trình nào có khả năng xảy ra? Có thể không xảy ra trong mã ứng dụng web không?Ngăn xếp ngăn xếp là gì?
Trả lời
Từ Wikipedia:
Trong các phần mềm, một chồng tràn xảy ra khi quá nhiều bộ nhớ được sử dụng trên gọi stack. Trong nhiều ngôn ngữ lập trình , ngăn xếp cuộc gọi chứa lượng bộ nhớ giới hạn, thường là được xác định khi bắt đầu chương trình .
Ngăn xếp là cấu trúc dữ liệu giữ hồ sơ về điểm các chương trình con của chương trình sẽ trả về điều khiển khi hoàn thành quá trình thực thi. Các địa chỉ trả về là được đẩy trong ngăn xếp khi các chương trình con đang được gọi, khi chương trình con kết thúc thực thi, địa chỉ trả về là được kéo từ ngăn xếp. Nếu có nhiều chương trình con và không có khoảng trống trong ngăn xếp thì tràn ngăn xếp sẽ xảy ra.
Cũng trong ngăn xếp được dự định để lưu các biến cục bộ, do đó nếu biến cục bộ quá lớn thì có thể xảy ra ngăn xếp không có không gian để lưu trữ, nếu trường hợp này xảy ra tràn ngăn xếp.
Wikipedia bao gồm một biểu đồ đẹp hình dung ngăn xếp khi một chương trình con DrawLine
được gọi từ một chương trình con khác được gọi là DrawSquare
, tôi hy vọng bức ảnh này giúp hiểu cấu trúc ngăn xếp tốt hơn.
Có hai nguyên nhân chính của một stack overflow: chức năng recursions sâu và chồng biến quá lớn. Vì đây là những thuật ngữ phổ biến trong hầu hết các ngôn ngữ lập trình, tràn bộ đệm có thể xảy ra bên cạnh sự phức tạp của ngôn ngữ.
Guffa đóng góp: Ngăn xếp không có liên quan gì đến việc thu thập rác.Các ứng dụng hiện đại có một ngăn xếp lớn hơn, khiến cho nó ít có khả năng bị tràn ngăn xếp hơn, nhưng khác hơn là không có sự khác biệt.
Từ những gì tôi hiểu, điều này cũng không xảy ra (ít nhất là không nhiều, tôi không thực sự chắc chắn) trong các ngôn ngữ hiện đại với bộ sưu tập rác thải. – thebrokencube
Tất nhiên nó có thể xảy ra trong một ngôn ngữ kịch bản. Họ có một cuộc gọi ngăn xếp, và có thể tràn ngập tự nhiên. – Guffa
Vâng, nó có thể xảy ra trong Java, ví dụ khi sử dụng một đệ quy rất sâu http://stackoverflow.com/questions/860550/stack-overflows-from-deep-recursion-in-java –
Từ wikipedia, của couse:
Trong các phần mềm, một chồng tràn xảy ra khi quá nhiều bộ nhớ được sử dụng trên các cuộc gọi stack. Trong nhiều ngôn ngữ lập trình, ngăn xếp cuộc gọi chứa một lượng bộ nhớ giới hạn, thường được xác định ở đầu chương trình. Kích thước của ngăn xếp cuộc gọi phụ thuộc vào nhiều yếu tố, bao gồm ngôn ngữ lập trình, kiến trúc máy, đa luồng và lượng bộ nhớ khả dụng. Khi quá nhiều bộ nhớ được sử dụng trên ngăn xếp cuộc gọi ngăn xếp được cho là tràn; thường dẫn đến sự cố chương trình. 1 Lớp lỗi phần mềm này thường do một trong hai loại lỗi lập trình gây ra bởi một trong hai loại lỗi lập trình
+1 Kinda lá bạn treo dù ... – steamer25
Đây không phải là câu trả lời tôi đang tìm kiếm –
nhưng câu trả lời này là tốt tôi nghĩ rằng –
ha, tiếng anh của bạn hơi khó hiểu, nhưng tôi nghĩ tôi nhận được yêu cầu của bạn.
tràn ngăn xếp xảy ra khi bạn đang sử dụng ngăn xếp (duh ...) và có sự cố cấp phát/đọc bộ nhớ. trong "chương trình web", khi bạn đặt nó (tôi giả sử bạn đang nói về HTML, PHP, JS), hoặc bạn không sử dụng ngăn xếp hoặc ngôn ngữ được sử dụng không cho phép kiểm soát bộ nhớ mức thấp ngăn ngừa những vấn đề này.
Thiếu kiểm soát cấp phát bộ nhớ không ** không ** ngăn chặn từ ngăn xếp tràn. –
Chỉ cần về mọi ngôn ngữ có một ngăn xếp cuộc gọi, nó là cần thiết để mã có thể trở lại nơi nó được sau khi một chương trình con kết thúc. Ngăn xếp cuộc gọi này thường có kích thước cố định, vì vậy sau khi gọi quá nhiều chương trình con mà không trả lại, ngăn xếp sẽ đầy và sẽ tràn. –
Ngăn xếp chứa một số khung ngăn xếp và được lưu trữ trong bộ nhớ. Mỗi khi một hàm được gọi, một khung ngăn xếp mới sẽ được thêm vào ngăn xếp. Một khung ngăn xếp chứa các đối số được chuyển tới hàm được gọi và địa chỉ trả về, để khi hàm được gọi đã hoàn thành, CPU biết nơi để quay lại để nó có thể tiếp tục thực hiện hàm gọi. Khung ngăn xếp cũng có thể chứa bộ nhớ được sử dụng bởi các biến cục bộ của hàm đang được gọi.
Trong ví dụ này, hàm gọi WriteCustomerDetails chính và kêu gọi PrintToConsole để viết ra các bit riêng lẻ của dữ liệu mà WriteCustomerDetails chức năng ngẩng đầu lên:
'======= đỉnh ngăn xếp ==== ================= '
Chức năng: PrintToConsole
Arg: John Smith, 34 Đại lộ Acacia, Tuổi 23
' ----------- ------------------------------------------------ '
Chức năng: WriteCustomerDetails
Arg: John Smith
'------------------------------------------------ ----------- '
Chức năng: Chính
' ====== dưới cùng của ngăn xếp =================== '
Xảy ra tràn ngăn xếp xảy ra nếu không đủ dung lượng cho ngăn xếp. Thông thường một ngăn xếp nằm trong một khối bộ nhớ liền kề lớn, do đó không được chia thành nhiều phần, điều này có nghĩa là một phần lớn bộ nhớ là cần thiết cho nó, và điều này khiến cho thời gian chạy trở nên khó khăn và tăng không gian dành riêng cho ngăn xếp nếu nó đầy.
Ngăn xếp chồng thường có thể xảy ra khi một hàm vô tình được viết tự gọi. Đôi khi nó là ok cho một chức năng để gọi chính nó miễn là có một 'nếu' hoặc một số điều kiện trong chức năng dừng các cuộc gọi tại một số điểm. Đây được gọi là hàm đệ quy. Nhưng, nếu không có dừng lại và chức năng tiếp tục gọi chính nó, hoặc có thể hai hoặc nhiều chức năng tiếp tục gọi nhau, sau đó rất nhanh chóng họ sẽ ăn tất cả các bộ nhớ ngăn xếp lên. Khi không còn gì, bạn sẽ gặp phải tình trạng tràn ngăn xếp và chương trình bị treo.
Điều này có thể xảy ra trong bất kỳ chương trình nào, chúng không nhất thiết phải phức tạp và có thể xảy ra khi mã chạy một trang web. Và, nó có thể xảy ra trong các ngôn ngữ kịch bản.
Câu trả lời rất hay, +1 –
Sự tràn ngăn xếp xảy ra khi bạn sử dụng quá nhiều không gian ngăn xếp. Thường có hai trường hợp khi điều này xảy ra:
Đầu tiên là khi bạn gặp lỗi trong mã, gây ra một vòng lặp đệ quy mà không cần thoát. Ví dụ: thuộc tính đọc từ chính nó:
public int Length {
get {
return Length;
}
}
Thứ hai là khi bạn có vòng lặp đệ quy quá sâu. Vì không gian ngăn xếp bị giới hạn, bạn chỉ có thể lồng một thuật toán một số lần nhất định. Nếu thuật toán của bạn được lồng vào nhau quá sâu để nó chạy ra khỏi không gian ngăn xếp trước khi nó tồn tại, bạn sẽ bị tràn ngăn xếp. Ví dụ:
public bool Odd(int value) {
if (value == 0) {
return false;
} else {
return !Odd(value - 1);
}
}
Nếu bạn gọi phương thức này có giá trị quá lớn, nó sẽ lồng quá sâu và gây tràn ngăn xếp.
Lý do cho việc tràn ngăn xếp trong cả hai ví dụ của bạn là đệ quy. Tuy nhiên, thực sự có một lý do khá đơn giản: Nếu một biến (cục bộ) hoặc đối số hàm được cấp phát trên ngăn xếp quá lớn, thường thì điều này sẽ xảy ra với các mảng, xem http://en.wikipedia.org/wiki/Stack_overflow –
http://en.wikipedia.org/wiki/Stack_overflow –