Giới hạn của ngăn xếp


10

Gần đây tôi đã kiểm tra giới hạn của ngăn xếp trên ba thiết bị với các hệ điều hành khác nhau (theo giới hạn, ý tôi là số cấp tối đa mà ngăn xếp có thể có) và tôi nhận thấy rằng mỗi khi tôi đạt 2 ^ 16 cấp thì nó mang lại cho tôi lỗi tràn, và khi tôi đặt 2 ^ 16-1 thì nó hoạt động bình thường.

Vì vậy, câu hỏi của tôi là - điều đó có đúng không? Liệu ngăn xếp có giới hạn tối đa 2 ^ 16-1 theo định nghĩa hay nó phụ thuộc vào HĐH?


5
here i mean by limit the maximum number of levels that can the stack havemột cấp độ là gì?
tkausl


3
Làm thế nào bạn đang thử nghiệm nó? Bạn có đang sử dụng 2 byte (dword) làm đầu vào không?
pro3carp3

6
Bạn đang sử dụng ngôn ngữ lập trình nào? Giới hạn rõ ràng như vậy ở một số cố định cho thấy đó là giới hạn có chủ ý bởi thời gian chạy cụ thể theo ngôn ngữ của bạn chứ không phải bởi kích thước ngăn xếp mà HĐH đã phân bổ. Ví dụ, python dường như thực thi giới hạn 1000 theo mặc định để ngăn bạn khỏi bị tràn ngăn xếp thực sự (phục hồi từ tràn ngăn xếp thực sự là khó khăn)
CodeInChaos

Câu trả lời:


20

Đó là hệ điều hành cụ thể (& cụ thể cho máy tính) và trên một số HĐH, bạn có một số cách để định cấu hình (và thậm chí tăng) giới hạn. Nó thậm chí là cụ thể của trình biên dịch (hoặc cụ thể theo ngôn ngữ lập trình của bạn), vì một số trình biên dịch (bao gồm GCC gần đây cho một số loại mã C giới hạn ) có thể tối ưu hóa một số lệnh gọi đuôi .

(một số đặc tả ngôn ngữ lập trình yêu cầu tối ưu hóa cuộc gọi đuôi, ví dụ R5RS )

Tôi không chắc câu hỏi của bạn có ý nghĩa (và chắc chắn không phải là giới hạn 2 16 của bạn ). Trên máy tính để bàn Linux của tôi (Debian / Sid / x86-64, Linux 4.9 kernel, RAM 32Gb, Intel i5-4690S), tôi có thể có một ngăn xếp cuộc gọi lên tới 8 megabyte (và tôi có thể tăng giới hạn đó, nếu tôi thực sự muốn ).

Đa luồngASLR đang làm cho câu hỏi của bạn phức tạp hơn nhiều . Xem ví dụ pthread_attr_setstack (3) . Đọc thêm về ngăn xếp phân chia (thường được sử dụng bởi các triển khai Go ) và về kiểu chuyển tiếp tiếp tục . Xem thêm câu trả lời này .

Để biết giá trị của nó, tôi chỉ thử mã C99 (và cả C11) sau đây:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void recfun(int x, int d) {
  printf("start recfun x=%d d=%d\n", x, d);
  fflush(NULL);
  if (d>0)
    recfun(x+1, d-1);
  printf("end recfun x=%d d=%d\n", x, d);
}

int main(int argc, char**argv) {
  int md = argc>1?atoi(argv[1]):10000;
  printf ("start md=%d\n", md);
  recfun(0, md);
  printf("end md=%d clock=%ld µs\n", md, clock());
}    
// eof recur.c

và tôi đã có thể chạy recurchương trình đó (được biên dịch với GCC 6 dưới dạng gcc -Wall -O recur.c -o recur) recur 161000 (vượt quá giới hạn 2 16 của bạn ). Với recur 256000nó cũng làm việc. Với recur 456000nó bị sập (với một tràn ngăn xếp cho cấp độ x=272057). Tôi không đủ kiên nhẫn cho các bài kiểm tra khác. Hãy thử điều đó trên máy tính của bạn. Đừng quên yêu cầu tối ưu hóa.

Một nguyên tắc nhỏ (đối với máy tính để bàn, máy tính xách tay, máy tính bảng) có thể là giữ cho ngăn xếp cuộc gọi của bạn dưới một megabyte.

Bằng cách chuyển -fstack-usage cho gcc tôi để nhận recur.sutệp sau (số được tính bằng byte, phù hợp với trực giác giới hạn ngăn xếp 8Mb của tôi; đừng quên mainkhung cuộc gọi và quan trọng hơn là bố trí ngăn xếp ban đầu, được cài đặt bởi kernel khi thực hiện (2 ) ..., cho crt0 ):

 recur.c:5:10:recfun    32  static
 recur.c:13:9:main  16  static

Tái bút Arduino của tôi có Atmega328 chỉ với 2Kbyte RAM, vì vậy chắc chắn không thể tái diễn nhiều như vậy. Tôi đoán chỉ có vài trăm khung xếp chồng là có thể thực tế nhất có thể trên Arduinos.


3

Kích thước ngăn xếp cho luồng chính của một tiến trình Windows được thiết lập bởi trình liên kết. Mặc định là 1MB nhưng có thể được điều chỉnh bằng công tắc / STACK. Các chủ đề được tạo sau này có thể sử dụng tham số dwStackSize của hàm CreateThread.

Vì vậy, nếu bạn đang thử nghiệm nhiều hệ điều hành Windows khác nhau, tất cả chúng đều có cùng kích thước ngăn xếp mặc định kể từ ít nhất là NT4.0.

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.