C / C ++ kích thước ngăn xếp tối đa của chương trình


115

Tôi muốn thực hiện DFS trên mảng 100 X 100. (Giả sử các phần tử của mảng đại diện cho các nút đồ thị) Vì vậy, giả sử trường hợp xấu nhất, độ sâu của các lệnh gọi hàm đệ quy có thể lên đến 10000 với mỗi lệnh gọi chiếm tối đa 20 byte. Vì vậy, nó có khả thi nghĩa là có khả năng xảy ra stackoverflow không?

Kích thước tối đa của ngăn xếp trong C / C ++ là bao nhiêu?

Vui lòng chỉ định gcc cho cả
2) cygwin trên Windows
2) Unix

Các giới hạn chung là gì?


11
Bạn có biết rằng bạn có thể thực hiện tìm kiếm theo chiều sâu mà không cần đệ quy, phải không?
Sebastian

4
Không, tôi không biết, xin vui lòng giải thích.
AVD

1
Tôi đã thực hiện một ví dụ nhỏ của DFS không đệ quy trong câu trả lời của tôi
Andreas Brinck

56
cộng với một cho một câu hỏi về stack overflow thực tế
Sam Watkins

3
@SamWatkins vâng, một trong những vấn đề lớn nhất đối với tôi với cái tên Tràn ngăn xếp là tôi có thể tra cứu "tràn ngăn xếp" trên Google và kết thúc trong trang web này, nhưng không nhất thiết / ít có khả năng xảy ra với các câu hỏi về tràn ngăn xếp ...
lalilulelost

Câu trả lời:


106

Trong Visual Studio, tôi nghĩ rằng kích thước ngăn xếp mặc định là 1 MB, vì vậy với độ sâu đệ quy là 10.000 mỗi khung ngăn xếp có thể tối đa là ~ 100 byte, đủ cho thuật toán DFS.

Hầu hết các trình biên dịch bao gồm Visual Studio cho phép bạn chỉ định kích thước ngăn xếp. Trên một số (tất cả?) Linux, kích thước ngăn xếp không phải là một phần của tệp thực thi mà là một biến môi trường trong Hệ điều hành. Sau đó, bạn có thể kiểm tra kích thước ngăn xếp với ulimit -svà đặt nó thành một giá trị mới với ví dụ ulimit -s 16384.

Đây là liên kết với kích thước ngăn xếp mặc định cho gcc.

DFS không có đệ quy:

std::stack<Node> dfs;
dfs.push(start);
do {
    Node top = dfs.top();
    if (top is what we are looking for) {
       break;
    }
    dfs.pop();
    for (outgoing nodes from top) {
        dfs.push(outgoing node);
    }
} while (!dfs.empty())

12
Và chỉ để tham khảo, BFS giống nhau ngoại trừ việc bạn sử dụng FIFO thay vì ngăn xếp.
Steve Jessop

Có, hoặc trong STL-lingo sử dụng std :: deque với pop_front / push_back
Andreas Brinck

DFS của bạn với kết quả ngăn xếp sẽ khác với phiên bản đệ quy. Trong một số trường hợp nó không quan trọng, nhưng những cái khác (. Cho ex trong loại topo) bạn sẽ nhận được kết quả sai
spin_eight

Có, giới hạn mặc định cho VS thực sự là 1MB. Có thể tìm thấy thêm thông tin và cách đặt giá trị khác trong tài liệu của Microsoft: msdn.microsoft.com/en-us/library/tdkhxaks(v=vs.140).aspx
FrankS101

Tôi thích sử dụng cấu trúc dữ liệu ngăn xếp rõ ràng cho các thuật toán như vậy hơn là đệ quy, để 1. không phụ thuộc vào kích thước của ngăn xếp hệ thống, 2. có thể thay đổi thuật toán để sử dụng cấu trúc dữ liệu khác, ví dụ như hàng đợi hoặc hàng đợi ưu tiên mà không cần ném ra tất cả các mã.
Sam Watkins

47

ngăn xếp cho các chủ đề thường nhỏ hơn. Bạn có thể thay đổi mặc định tại thời điểm liên kết hoặc cũng có thể thay đổi tại thời điểm chạy. Để tham khảo, một số giá trị mặc định là:

  • glibc i386, x86_64 7,4 MB
  • Tru64 5.1 5.2 MB
  • Cygwin 1.8 MB
  • Solaris 7..10 1 MB
  • MacOS X 10.5 460 KB
  • AIX 5 98 KB
  • OpenBSD 4.0 64 KB
  • HP-UX 11 16 KB

14
Được xác định theo kinh nghiệm bởi Bruno Haible list.gnu.org/archive/html/bug-coreutils/2009-10/msg00262.html
pixelbeat

17

Phụ thuộc vào nền tảng, phụ thuộc vào chuỗi công cụ, phụ thuộc vào ulimit, phụ thuộc vào tham số .... Nó hoàn toàn không được chỉ định và có rất nhiều thuộc tính tĩnh và động có thể ảnh hưởng đến nó.


4
Không có "giới hạn chung". Trên Windows, với các tùy chọn trình liên kết VC ++ mặc định và hành vi CreateThread mặc định, thường khoảng 1 MiB cho mỗi luồng. Trên Linux, với lượng người dùng không giới hạn, tôi tin rằng thường không có giới hạn (ngăn xếp chỉ có thể phát triển xuống dưới để chiếm gần như toàn bộ không gian địa chỉ). Về cơ bản, nếu bạn phải hỏi, bạn không nên sử dụng ngăn xếp.
DrPizza

1
Trên hệ thống nhúng, bạn có thể có 4k hoặc ít hơn. Trong trường hợp đó, bạn phải hỏi ngay cả khi sử dụng ngăn xếp là hợp lý. Câu trả lời thường là một cái nhún vai của Gallic.
Steve Jessop

1
Ah đúng, cũng thường xảy ra trong chế độ hạt nhân.
DrPizza

6

Có, có khả năng tràn ngăn xếp. Tiêu chuẩn C và C ++ không quy định những thứ như độ sâu ngăn xếp, chúng thường là một vấn đề môi trường.

Hầu hết các môi trường phát triển tốt và / hoặc hệ điều hành sẽ cho phép bạn điều chỉnh kích thước ngăn xếp của một quy trình, ở thời gian liên kết hoặc thời gian tải.

Bạn nên chỉ định hệ điều hành và môi trường phát triển bạn đang sử dụng để được hỗ trợ có mục tiêu hơn.

Ví dụ: trong Ubuntu Karmic Koala, mặc định cho gcc là 2M dành riêng và cam kết 4K nhưng điều này có thể được thay đổi khi bạn liên kết chương trình. Sử dụng --stacktùy chọn ldđể làm điều đó.


2
@lex: không có giới hạn chung. Nó phụ thuộc vào rất nhiều thông số.
Michael Foukarakis

@paxdiablo: WHat là nghĩa của từ dành riêng và cam kết?
AVD

2
Dự trữ là bao nhiêu không gian địa chỉ để phân bổ, cam kết là bao nhiêu để đính kèm lưu trữ sao lưu. Nói cách khác, không gian địa chỉ dành riêng không có nghĩa là bộ nhớ sẽ ở đó khi bạn cần. Nếu bạn không bao giờ sử dụng nhiều hơn ngăn xếp 4K, bạn sẽ không lãng phí bộ nhớ thực cho 1,6 triệu còn lại. Nếu bạn muốn đảm bảo sẽ có đủ ngăn xếp, dự trữ và cam kết phải giống hệt nhau.
paxdiablo

2
@paxdiablo 2M - 4k không phải là 1,6M. Chỉ nói. (đã khiến tôi bối rối trong 3 lần đầu tiên tôi đọc bình luận của bạn)
Griffin

2
@griffin, kudo cho người đầu tiên đạt được điều đó sau hơn 3 năm. Tôi tất nhiên có nghĩa là "nghỉ ngơi của nó" - Tôi sẽ tránh được một con số thực tế để không làm cho một sai lầm có thể :-)
paxdiablo

5

Tôi vừa hết ngăn xếp tại nơi làm việc, đó là một cơ sở dữ liệu và nó đang chạy một số luồng, về cơ bản nhà phát triển trước đó đã ném một mảng lớn lên ngăn xếp và dù sao thì ngăn xếp cũng thấp. Phần mềm được biên dịch bằng Microsoft Visual Studio 2015.

Mặc dù luồng đã hết ngăn xếp, nó vẫn âm thầm không thành công và tiếp tục, nó chỉ tràn ngăn xếp khi truy cập nội dung của dữ liệu trên ngăn xếp.

Lời khuyên tốt nhất mà tôi có thể đưa ra là không khai báo mảng trên ngăn xếp - đặc biệt là trong các ứng dụng phức tạp và đặc biệt là trong các luồng, thay vào đó hãy sử dụng heap. Đó là những gì nó ở đó;)

Cũng chỉ cần lưu ý rằng nó có thể không thất bại ngay lập tức khi khai báo ngăn xếp, nhưng chỉ khi truy cập. Tôi đoán là trình biên dịch khai báo ngăn xếp dưới các cửa sổ một cách "lạc quan", tức là nó sẽ giả định rằng ngăn xếp đã được khai báo và có đủ kích thước cho đến khi sử dụng nó và sau đó phát hiện ra rằng ngăn xếp không có ở đó.

Các hệ điều hành khác nhau có thể có các chính sách khai báo ngăn xếp khác nhau. Vui lòng để lại bình luận nếu bạn biết những chính sách này là gì.


3

Tôi không chắc ý của bạn khi thực hiện tìm kiếm theo chiều sâu trên một mảng hình chữ nhật, nhưng tôi cho rằng bạn biết mình đang làm gì.

Nếu giới hạn ngăn xếp là một vấn đề, bạn có thể chuyển đổi giải pháp đệ quy của mình thành một giải pháp lặp lại để đẩy các giá trị trung gian lên một ngăn xếp được phân bổ từ heap.

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.