2009-11-01 38 views
5

Bạn có thể đưa ra ví dụ về tràn ngăn xếp trong C++ không? Khác với trường hợp đệ quy:Bạn có thể đưa ra ví dụ về tràn ngăn xếp trong C++ không?

void foo() { foo(); } 
+11

Bạn muốn tôi thực hiện trang web toàn stackoverflow trong C++ trong câu trả lời của tôi không? Wow ... :) – dicroce

+0

@dicroce: lol +1 :-) –

+0

Tại sao không phải là vô hạn đệ quy một câu trả lời chấp nhận được? – outis

Trả lời

14

Trường hợp điển hình không liên quan đến đệ quy vô hạn là khai báo một biến tự động trên ngăn xếp quá lớn. Ví dụ:

int foo() 
{ 
    int array[1000000]; 

} 
6
void function() 
{ 
function(); 
} 
+1

+1 sạch sẽ và đơn giản. Đây là tất cả bạn cần để thổi ngăn xếp. –

+1

Chúng ta có thể làm cho nó ngắn hơn không? Có, chúng tôi có thể! 'void _() {_();}' ... nó gần giống như Perl;) – Thomas

+1

Sự khác biệt là, trong vùng đất Perl, có nhiều khả năng bạn sẽ thổi * stack của bạn trước khi Perl làm. – Rob

1

Ví dụ này thể hiện đệ quy không kiểm soát được. Cuối cùng, khoảng cách ngăn xếp được phân bổ cho quá trình này sẽ hoàn toàn bị ghi đè bởi các trường hợp thanh và ...

int foo(int bar) 
{ 
    int ret = foo(42); 
    return ret; 
} 
3

Hãy cố gắng trả lại chính cho đến khi ngăn xếp hết?

int main(int argc, char **argv) 
{ 
    return main(argc, argv); 
} 
+3

() trong C++. – Tmdean

+0

Tôi biết nó sẽ không định dạng chính xác, nhưng không có cảnh báo với '-Wall' ngay cả đối với chương trình thích hợp này: int main(int argc, char **argv) { if (argc == 0){return 0;} else {std::cout << argc << std::endl; return main(0, argv);} }

+0

Tôi có nghĩa là kỳ quặc rằng' g ++ 'không đưa ra bất kỳ cảnh báo nào khi bạn gọi chính; bạn thực sự là đúng (từ những gì tôi đã nhìn thấy) rằng các tiêu chuẩn không cho phép gọi 'chính'. –

0

Infinite đệ quy:

 
void infiniteFunction() 
{ 
    infiniteFunction(); 
} 

int main() 
{ 
    infiniteFunction(); 
    return 0; 
} 
5

Đây là một loại có thể xảy ra trong thực tế:

int factorial(int x) { 
    return x == 0 ? 1 : x * factorial(x-1); 
} 

này tràn ngăn xếp cho tiêu cực x. Và, as Frank Krueger mentioned, cũng cho quá lớn x (nhưng sau đó int sẽ tràn trước).

3

Theo chỉnh sửa :-)

void ping() 
{ 
    pong(); 
} 

void pong() 
{ 
ping(); 
} 

Ngoài ra, tôi tin rằng bạn có thể nhận được stack overflow nếu bạn cố gắng phân bổ không gian hơn tối đa thread stack kích thước (1MB theo mặc định trong VS), vì vậy cái gì đó như int a[100000]; nên cung cấp ngoại lệ.

+0

gọi chúng là ping và pong lol Nice one –

+0

yeah, một tên hài hước! –

2

Tôi không thể tin rằng chúng tôi đã thoát khỏi ví dụ đệ quy vĩ đại nhất mọi thời đại, giai thừa!

#include <stdio.h> 

double fact(double n) { 
    if (n <= 0) return 1; 
    else return n * fact(n - 1); 
} 

int main() { 
    printf("fact(5) = %g\n", fact(5)); 
    printf("fact(10) = %g\n", fact(10)); 
    printf("fact(100) = %g\n", fact(100)); 
    printf("fact(1000) = %g\n", fact(1000)); 
    printf("fact(1000000) = %g\n", fact(1000000)); 
} 

Trên OS X 10.5.8 với GCC 4.0.1:

$ gcc f.c -o f && ./f 
fact(5) = 120 
fact(10) = 3.6288e+06 
fact(100) = 9.33262e+157 
fact(1000) = inf 
Segmentation fault 

Thật không may, OS X báo cáo một "Segmentation lỗi" thay vì một "Stack tràn". Quá tệ.

0

Bạn cũng có thể bị tràn ngăn xếp nếu bạn cố gắng đặt các đối tượng lớn lên ngăn xếp (theo giá trị).

1

Nếu bạn muốn tạo một chương trình rõ ràng không đệ quy để dẫn đến một chồng tràn bởi chức năng cuộc gọi: sản lượng

#!/usr/bin/env python 
import sys 

print "void func" + sys.argv[1] + "() { }" 
for i in xrange(int(sys.argv[1])-1, -1, -1): 
    print "void func" + str(i) + "() { func" + str(i+1) + "(); }" 
print "int main() { func0(); return 0; }" 

mẫu:

$ python recursion.py 5 
void func5() { } 
void func4() { func5(); } 
void func3() { func4(); } 
void func2() { func3(); } 
void func1() { func2(); } 
void func0() { func1(); } 
int main() { func0(); return 0; } 

sử dụng mẫu:

$ python recursion.py 250000 | g++ -x c++ - && ./a.out 

Ít nhất trên hệ thống của tôi, ngăn xếp cuộc gọi có nghĩa là 174602, vì vậy bạn cần đặt đối số là recursion.py để lớn hơn số đó; và phải mất vài phút để biên dịch và liên kết chương trình.

3

Compile-time dụ:

template <int N> 
struct Factorial { 
    enum { value = N * Factorial<N - 1>::value }; 
}; 

// ... 
{ 
    int overflow = Factorial<10>::value; 
} 
Các vấn đề liên quan