StackOverflowError là gì?


439

Điều gì là StackOverflowErrornguyên nhân gây ra nó và tôi nên giải quyết chúng như thế nào?


Kích thước ngăn xếp trong java là nhỏ. Và một số lần như nhiều cuộc gọi đệ quy bạn phải đối mặt với vấn đề này. Bạn có thể thiết kế lại mã của bạn bằng vòng lặp. Bạn có thể tìm thấy mẫu thiết kế chung để thực hiện trong url này: jndanial.com/73
JNDanial

Một cách không rõ ràng để có được nó: thêm dòng new Object() {{getClass().newInstance();}};vào một số bối cảnh tĩnh (ví dụ: mainphương thức). Không hoạt động từ bối cảnh ví dụ (chỉ ném InstantiationException).
John McClane

Câu trả lời:


408

Các tham số và biến cục bộ được phân bổ trên ngăn xếp (với các kiểu tham chiếu, đối tượng sống trên heap và một biến trong ngăn xếp tham chiếu đối tượng trên heap). Ngăn xếp thường sống ở đầu trên của không gian địa chỉ của bạn và khi nó được sử dụng hết, nó sẽ hướng về phía dưới cùng của không gian địa chỉ (tức là về không).

Quá trình của bạn cũng có một đống , mà sống ở đáy cuối quá trình của bạn. Khi bạn phân bổ bộ nhớ, heap này có thể phát triển về phía trên của không gian địa chỉ của bạn. Như bạn có thể thấy, có khả năng heap "va chạm" với stack (hơi giống các mảng kiến ​​tạo !!!).

Nguyên nhân phổ biến cho tràn ngăn xếp là một cuộc gọi đệ quy xấu . Thông thường, điều này được gây ra khi các hàm đệ quy của bạn không có điều kiện kết thúc chính xác, vì vậy nó sẽ tự gọi mãi mãi. Hoặc khi điều kiện chấm dứt tốt, nó có thể được gây ra bằng cách yêu cầu quá nhiều cuộc gọi đệ quy trước khi thực hiện nó.

Tuy nhiên, với lập trình GUI, có thể tạo đệ quy gián tiếp . Ví dụ: ứng dụng của bạn có thể xử lý các thông báo sơn và trong khi xử lý chúng, nó có thể gọi một chức năng khiến hệ thống gửi một thông điệp sơn khác. Ở đây bạn không tự gọi mình một cách rõ ràng, nhưng OS / VM đã làm điều đó cho bạn.

Để đối phó với họ, bạn sẽ cần kiểm tra mã của mình. Nếu bạn có chức năng tự gọi thì hãy kiểm tra xem bạn đã có tình trạng chấm dứt chưa. Nếu bạn có, thì hãy kiểm tra xem khi gọi hàm, bạn đã sửa đổi ít nhất một trong các đối số, nếu không sẽ không có thay đổi rõ ràng cho hàm được gọi đệ quy và điều kiện kết thúc là vô ích. Cũng lưu ý rằng không gian ngăn xếp của bạn có thể hết bộ nhớ trước khi đạt đến điều kiện kết thúc hợp lệ, do đó hãy đảm bảo phương thức của bạn có thể xử lý các giá trị đầu vào yêu cầu nhiều cuộc gọi đệ quy hơn.

Nếu bạn không có các hàm đệ quy rõ ràng thì hãy kiểm tra xem liệu bạn có gọi bất kỳ hàm thư viện nào gián tiếp sẽ khiến hàm của bạn được gọi không (như trường hợp ẩn ở trên).


1
Áp phích gốc: hey điều này thật tuyệt. Vì vậy, đệ quy luôn có trách nhiệm cho ngăn xếp tràn? Hoặc những thứ khác có thể chịu trách nhiệm cho họ là tốt? Thật không may, tôi đang sử dụng một thư viện ... nhưng không phải là một thư viện mà tôi hiểu.
Ziggy

4
Ha ha ha, vì vậy đây là: while (points <100) {addMouseListener (); bóng di chuyển (); kiểm tra kiểm tra (); tạm dừng (tốc độ);} Wow tôi cảm thấy khập khiễng vì không nhận ra rằng tôi sẽ kết thúc với một đống người nghe chuột ... Cảm ơn các bạn!
Ziggy

4
Không, tràn ngăn xếp cũng có thể đến từ các biến quá lớn để phân bổ trên ngăn xếp nếu bạn tra cứu bài viết Wikipedia về nó tại en.wikipedia.org/wiki/Stack_overflow .
JB King

8
Cần phải chỉ ra rằng gần như không thể "xử lý" lỗi tràn ngăn xếp. Trong hầu hết các môi trường, để xử lý lỗi người ta cần chạy mã trên ngăn xếp, điều này rất khó nếu không có thêm không gian ngăn xếp.
Licks nóng

3
@JB King: Không thực sự áp dụng cho Java, nơi chỉ có các kiểu và tham chiếu nguyên thủy được lưu giữ trên ngăn xếp. Tất cả các công cụ lớn (mảng và đối tượng) là trên đống.
jcsahnwaldt nói GoFundMonica

107

Để mô tả điều này, trước tiên hãy cho chúng tôi hiểu cách các biến và đối tượng cục bộ được lưu trữ.

Biến cục bộ được lưu trữ trong ngăn xếp : nhập mô tả hình ảnh ở đây

Nếu bạn nhìn vào hình ảnh, bạn sẽ có thể hiểu mọi thứ đang hoạt động như thế nào.

Khi một lệnh gọi hàm được gọi bởi một ứng dụng Java, một khung ngăn xếp được phân bổ trên ngăn xếp cuộc gọi. Khung ngăn xếp chứa các tham số của phương thức được gọi, các tham số cục bộ của nó và địa chỉ trả về của phương thức. Địa chỉ trả về biểu thị điểm thực hiện từ đó, việc thực hiện chương trình sẽ tiếp tục sau khi phương thức được gọi trả về. Nếu không có không gian cho khung ngăn xếp mới thì StackOverflowErrormáy ảo Java (JVM) sẽ bị ném.

Trường hợp phổ biến nhất có thể làm cạn kiệt ngăn xếp của ứng dụng Java là đệ quy. Trong đệ quy, một phương thức gọi chính nó trong khi thực hiện. Đệ quy được coi là một kỹ thuật lập trình đa năng mạnh mẽ nhưng phải được sử dụng một cách thận trọng, để tránhStackOverflowError .

Một ví dụ về ném a StackOverflowErrorđược hiển thị dưới đây:

StackOverflowErrorExample.java:

public class StackOverflowErrorExample {

  public static void recursivePrint(int num) {
    System.out.println("Number: " + num);

    if (num == 0)
      return;
    else
      recursivePrint(++num);
  }

  public static void main(String[] args) {
    StackOverflowErrorExample.recursivePrint(1);
  }
}

Trong ví dụ này, chúng tôi định nghĩa một phương thức đệ quy, được gọi là recursivePrint in một số nguyên và sau đó, tự gọi nó, với số nguyên liên tiếp tiếp theo làm đối số. Đệ quy kết thúc cho đến khi chúng ta truyền vào 0như một tham số. Tuy nhiên, trong ví dụ của chúng tôi, chúng tôi đã chuyển tham số từ 1 và theo dõi ngày càng tăng của nó, do đó, đệ quy sẽ không bao giờ chấm dứt.

Một thực thi mẫu, sử dụng -Xss1M cờ chỉ định kích thước của ngăn xếp luồng bằng 1MB, được hiển thị bên dưới:

Number: 1
Number: 2
Number: 3
...
Number: 6262
Number: 6263
Number: 6264
Number: 6265
Number: 6266
Exception in thread "main" java.lang.StackOverflowError
        at java.io.PrintStream.write(PrintStream.java:480)
        at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
        at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
        at sun.nio.cs.StreamEncoder.flushBuffer(StreamEncoder.java:104)
        at java.io.OutputStreamWriter.flushBuffer(OutputStreamWriter.java:185)
        at java.io.PrintStream.write(PrintStream.java:527)
        at java.io.PrintStream.print(PrintStream.java:669)
        at java.io.PrintStream.println(PrintStream.java:806)
        at StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:4)
        at StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:9)
        at StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:9)
        at StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:9)
        ...

Tùy thuộc vào cấu hình ban đầu của JVM, kết quả có thể khác nhau, nhưng cuối cùng StackOverflowError sẽ bị ném. Ví dụ này là một ví dụ rất hay về cách đệ quy có thể gây ra vấn đề, nếu không được thực hiện một cách thận trọng.

Cách đối phó với StackOverflowError

  1. Giải pháp đơn giản nhất là kiểm tra cẩn thận dấu vết ngăn xếp và phát hiện mẫu lặp lại của số dòng. Các số dòng này cho biết mã được gọi đệ quy. Khi bạn phát hiện các dòng này, bạn phải kiểm tra cẩn thận mã của mình và hiểu lý do tại sao đệ quy không bao giờ chấm dứt.

  2. Nếu bạn đã xác minh rằng đệ quy được triển khai chính xác, bạn có thể tăng kích thước của ngăn xếp, để cho phép số lượng yêu cầu lớn hơn. Tùy thuộc vào Máy ảo Java (JVM) được cài đặt, kích thước ngăn xếp luồng mặc định có thể bằng 512KB hoặc 1MB . Bạn có thể tăng kích thước ngăn xếp luồng bằng -Xsscờ. Cờ này có thể được chỉ định thông qua cấu hình của dự án hoặc thông qua dòng lệnh. Định dạng của -Xssđối số là: -Xss<size>[g|G|m|M|k|K]


Dường như có một lỗi trong một số phiên bản java khi sử dụng windows trong đó đối số -Xss chỉ có hiệu lực trên các luồng mới
goerlibe

65

Nếu bạn có một chức năng như:

int foo()
{
    // more stuff
    foo();
}

Sau đó, foo () sẽ tiếp tục gọi chính nó, ngày càng sâu hơn và khi không gian được sử dụng để theo dõi các chức năng bạn đang điền vào, bạn sẽ gặp lỗi tràn ngăn xếp.


12
Sai lầm. Chức năng của bạn là đệ quy đuôi. Hầu hết các ngôn ngữ được biên dịch có tối ưu hóa đệ quy đuôi. Điều này có nghĩa là đệ quy giảm thành một vòng lặp đơn giản và bạn sẽ không bao giờ đạt được lỗi tràn stack với đoạn mã này trên một số hệ thống.
Vui vẻ

Cheery, ngôn ngữ phi chức năng hỗ trợ đệ quy đuôi?
Horseyguy

@banister và một số triển khai javascript
Pacerier

@horseyguy Scala có hỗ trợ đệ quy Tail.
Ajit K'sagar

Điều này nắm bắt bản chất của những gì có thể tạo ra một ngăn xếp tràn. Đẹp.
Pixel

24

Tràn ngăn xếp có nghĩa chính xác là: một ngăn xếp tràn. Thông thường có một ngăn xếp trong chương trình chứa các biến phạm vi cục bộ và địa chỉ nơi sẽ trả về khi việc thực hiện một thường trình kết thúc. Ngăn xếp đó có xu hướng là một phạm vi bộ nhớ cố định ở đâu đó trong bộ nhớ, do đó nó giới hạn số lượng có thể chứa các giá trị.

Nếu ngăn xếp trống, bạn không thể bật, nếu bạn sẽ gặp lỗi tràn ngăn xếp.

Nếu ngăn xếp đầy, bạn không thể đẩy, nếu bạn sẽ gặp lỗi tràn ngăn xếp.

Vì vậy, tràn ngăn xếp xuất hiện nơi bạn phân bổ quá nhiều vào ngăn xếp. Ví dụ, trong đệ quy đã đề cập.

Một số thực hiện tối ưu hóa ra một số hình thức thu hồi. Đuôi đệ quy nói riêng. Các thói quen đệ quy đuôi là một dạng các thói quen trong đó cuộc gọi đệ quy xuất hiện như một điều cuối cùng mà thói quen thường làm. Cuộc gọi thông thường như vậy chỉ đơn giản là giảm thành một bước nhảy.

Một số triển khai đi xa đến mức thực hiện các ngăn xếp riêng của chúng để đệ quy, do đó chúng cho phép đệ quy tiếp tục cho đến khi hệ thống hết bộ nhớ.

Điều dễ nhất bạn có thể thử là tăng kích thước ngăn xếp nếu có thể. Nếu bạn không thể làm điều đó, điều tốt nhất thứ hai sẽ là xem liệu có thứ gì đó rõ ràng gây ra tràn ngăn xếp hay không. Hãy thử nó bằng cách in một cái gì đó trước và sau cuộc gọi thành thói quen. Điều này giúp bạn tìm ra thói quen thất bại.


4
Có một điều như một chồng underflow ?
Pacerier

5
Có thể lắp ráp một ngăn xếp ngăn xếp (xuất hiện nhiều hơn bạn đã đẩy), mặc dù trong các ngôn ngữ được biên dịch, điều đó gần như là không thể. Tôi không chắc chắn, bạn có thể tìm thấy cách triển khai alloca () "hỗ trợ" kích thước âm.
Score_Under

2
Tràn ngăn xếp có nghĩa chính xác là: một ngăn xếp tràn. Thông thường có một ngăn xếp trong chương trình chứa các biến phạm vi cục bộ -> Không, mỗi luồng có ngăn xếp riêng chứa các khung ngăn xếp cho mọi lệnh gọi phương thức có chứa các biến cục bộ ..
Koray Tugay

9

Một tràn ngăn xếp thường được gọi bằng cách gọi hàm lồng nhau quá sâu (đặc biệt dễ dàng khi sử dụng đệ quy, tức là một hàm tự gọi) hoặc phân bổ một lượng lớn bộ nhớ trên ngăn xếp trong đó sử dụng heap sẽ phù hợp hơn.


1
Rất tiếc, đã không thấy thẻ Java
Greg

Ngoài ra, từ các poster ban đầu ở đây: chức năng lồng nhau quá sâu trong những gì? Cac chưc năng khac? Và: làm thế nào để phân bổ bộ nhớ cho ngăn xếp hoặc đống (vì, bạn biết đấy, tôi đã thực hiện rõ ràng một trong những điều này mà không biết).
Ziggy

@Ziggy: Có, nếu một hàm gọi một hàm khác, gọi một hàm khác, và sau đó, sau nhiều cấp độ, chương trình của bạn sẽ có một ngăn xếp tràn. [tiếp tục]
Chris Jester-Young

[... tiếp tục] Trong Java, bạn không thể phân bổ trực tiếp bộ nhớ từ ngăn xếp (trong khi ở C, bạn có thể, và đây sẽ là thứ cần theo dõi), vì vậy đó không phải là nguyên nhân. Trong Java, tất cả các phân bổ trực tiếp đến từ heap, bằng cách sử dụng "mới".
Chris Jester-Young

@ ChrisJester-Young Không phải sự thật là nếu tôi có 100 biến cục bộ trong một phương thức, thì tất cả đều đi vào ngăn xếp mà không có ngoại lệ?
Pacerier

7

Giống như bạn nói, bạn cần hiển thị một số mã. :-)

Lỗi tràn ngăn xếp thường xảy ra khi hàm của bạn gọi tổ quá sâu. Xem chủ đề Stack Overflow Code Golf để biết một số ví dụ về cách điều này xảy ra (mặc dù trong trường hợp của câu hỏi đó, các câu trả lời cố tình gây ra lỗi tràn stack).


1
Tôi hoàn toàn muốn thêm mã, nhưng vì tôi không biết nguyên nhân nào khiến ngăn xếp tràn ra nên tôi không chắc nên thêm mã nào. Thêm tất cả các mã sẽ là khập khiễng, không?
Ziggy

Dự án của bạn là nguồn mở? Nếu vậy, chỉ cần tạo một tài khoản Sourceforge hoặc github và tải lên tất cả mã của bạn ở đó. :-)
Chris Jester-Young

Điều này nghe có vẻ là một ý tưởng tuyệt vời, nhưng tôi là một người không biết rằng tôi thậm chí không biết những gì tôi sẽ phải tải lên. Giống như, thư viện mà tôi đang nhập các lớp mà tôi đang mở rộng, v.v ... đều là những ẩn số đối với tôi. Người đàn ông: thời gian tồi tệ.
Ziggy


5

StackOverflowErrorlà để ngăn xếp như OutOfMemoryErrorlà đống.

Các cuộc gọi đệ quy không giới hạn dẫn đến không gian ngăn xếp được sử dụng hết.

Ví dụ sau đây tạo ra StackOverflowError:

class  StackOverflowDemo
{
    public static void unboundedRecursiveCall() {
     unboundedRecursiveCall();
    }

    public static void main(String[] args) 
    {
        unboundedRecursiveCall();
    }
}

StackOverflowError là có thể tránh được nếu các cuộc gọi đệ quy bị chặn để ngăn tổng số các cuộc gọi trong bộ nhớ chưa hoàn thành (tính bằng byte) vượt quá kích thước ngăn xếp (tính bằng byte).


3

Dưới đây là một ví dụ về thuật toán đệ quy để đảo ngược danh sách liên kết đơn. Trên máy tính xách tay có thông số kỹ thuật sau (bộ nhớ 4G, CPU Intel Core i5 2.3GHz, Windows 7 64 bit), chức năng này sẽ gặp phải lỗi StackOverflow cho danh sách kích thước được liên kết gần 10.000.

Quan điểm của tôi là chúng ta nên sử dụng đệ quy một cách thận trọng, luôn luôn tính đến quy mô của hệ thống. Thường đệ quy có thể được chuyển đổi sang chương trình lặp, mà quy mô tốt hơn. (Một phiên bản lặp lại của cùng một thuật toán được đưa ra ở dưới cùng của trang, nó đảo ngược danh sách liên kết đơn có kích thước 1 triệu trong 9 mili giây.)

    private static LinkedListNode doReverseRecursively(LinkedListNode x, LinkedListNode first){

    LinkedListNode second = first.next;

    first.next = x;

    if(second != null){
        return doReverseRecursively(first, second);
    }else{
        return first;
    }
}

public static LinkedListNode reverseRecursively(LinkedListNode head){
    return doReverseRecursively(null, head);
}

Phiên bản lặp của cùng một thuật toán:

    public static LinkedListNode reverseIteratively(LinkedListNode head){
    return doReverseIteratively(null, head);
}   

private static LinkedListNode doReverseIteratively(LinkedListNode x, LinkedListNode first) {

    while (first != null) {
        LinkedListNode second = first.next;
        first.next = x;
        x = first;

        if (second == null) {
            break;
        } else {
            first = second;
        }
    }
    return first;
}


public static LinkedListNode reverseIteratively(LinkedListNode head){
    return doReverseIteratively(null, head);
}

Tôi nghĩ với JVM, nó thực sự không quan trọng thông số kỹ thuật của máy tính xách tay của bạn.
kevin

3

A StackOverflowErrorlà một lỗi thời gian chạy trong java.

Nó được ném khi vượt quá số lượng bộ nhớ ngăn xếp cuộc gọi được phân bổ bởi JVM.

Một trường hợp phổ biến của StackOverflowErrorviệc bị ném, là khi ngăn xếp cuộc gọi vượt quá do đệ quy quá sâu hoặc vô hạn.

Thí dụ:

public class Factorial {
    public static int factorial(int n){
        if(n == 1){
            return 1;
        }
        else{
            return n * factorial(n-1);
        }
    }

    public static void main(String[] args){
        System.out.println("Main method started");
        int result = Factorial.factorial(-1);
        System.out.println("Factorial ==>"+result);
        System.out.println("Main method ended");
    }
}

Dấu vết ngăn xếp:

Main method started
Exception in thread "main" java.lang.StackOverflowError
at com.program.stackoverflow.Factorial.factorial(Factorial.java:9)
at com.program.stackoverflow.Factorial.factorial(Factorial.java:9)
at com.program.stackoverflow.Factorial.factorial(Factorial.java:9)

Trong trường hợp trên, có thể tránh được bằng cách thực hiện các thay đổi theo chương trình. Nhưng nếu logic chương trình là chính xác và nó vẫn xảy ra thì kích thước ngăn xếp của bạn cần phải tăng lên.


0

Đây là một trường hợp điển hình của java.lang.StackOverflowError... Phương thức này tự gọi đệ quy mà không có lối ra doubleValue(),floatValue() vv

Rational.java

    public class Rational extends Number implements Comparable<Rational> {
        private int num;
        private int denom;

        public Rational(int num, int denom) {
            this.num = num;
            this.denom = denom;
        }

        public int compareTo(Rational r) {
            if ((num / denom) - (r.num / r.denom) > 0) {
                return +1;
            } else if ((num / denom) - (r.num / r.denom) < 0) {
                return -1;
            }
            return 0;
        }

        public Rational add(Rational r) {
            return new Rational(num + r.num, denom + r.denom);
        }

        public Rational sub(Rational r) {
            return new Rational(num - r.num, denom - r.denom);
        }

        public Rational mul(Rational r) {
            return new Rational(num * r.num, denom * r.denom);
        }

        public Rational div(Rational r) {
            return new Rational(num * r.denom, denom * r.num);
        }

        public int gcd(Rational r) {
            int i = 1;
            while (i != 0) {
                i = denom % r.denom;
                denom = r.denom;
                r.denom = i;
            }
            return denom;
        }

        public String toString() {
            String a = num + "/" + denom;
            return a;
        }

        public double doubleValue() {
            return (double) doubleValue();
        }

        public float floatValue() {
            return (float) floatValue();
        }

        public int intValue() {
            return (int) intValue();
        }

        public long longValue() {
            return (long) longValue();
        }
    }

Main.java

    public class Main {

        public static void main(String[] args) {

            Rational a = new Rational(2, 4);
            Rational b = new Rational(2, 6);

            System.out.println(a + " + " + b + " = " + a.add(b));
            System.out.println(a + " - " + b + " = " + a.sub(b));
            System.out.println(a + " * " + b + " = " + a.mul(b));
            System.out.println(a + " / " + b + " = " + a.div(b));

            Rational[] arr = {new Rational(7, 1), new Rational(6, 1),
                    new Rational(5, 1), new Rational(4, 1),
                    new Rational(3, 1), new Rational(2, 1),
                    new Rational(1, 1), new Rational(1, 2),
                    new Rational(1, 3), new Rational(1, 4),
                    new Rational(1, 5), new Rational(1, 6),
                    new Rational(1, 7), new Rational(1, 8),
                    new Rational(1, 9), new Rational(0, 1)};

            selectSort(arr);

            for (int i = 0; i < arr.length - 1; ++i) {
                if (arr[i].compareTo(arr[i + 1]) > 0) {
                    System.exit(1);
                }
            }


            Number n = new Rational(3, 2);

            System.out.println(n.doubleValue());
            System.out.println(n.floatValue());
            System.out.println(n.intValue());
            System.out.println(n.longValue());
        }

        public static <T extends Comparable<? super T>> void selectSort(T[] array) {

            T temp;
            int mini;

            for (int i = 0; i < array.length - 1; ++i) {

                mini = i;

                for (int j = i + 1; j < array.length; ++j) {
                    if (array[j].compareTo(array[mini]) < 0) {
                        mini = j;
                    }
                }

                if (i != mini) {
                    temp = array[i];
                    array[i] = array[mini];
                    array[mini] = temp;
                }
            }
        }
    }

Kết quả

    2/4 + 2/6 = 4/10
    Exception in thread "main" java.lang.StackOverflowError
    2/4 - 2/6 = 0/-2
        at com.xetrasu.Rational.doubleValue(Rational.java:64)
    2/4 * 2/6 = 4/24
        at com.xetrasu.Rational.doubleValue(Rational.java:64)
    2/4 / 2/6 = 12/8
        at com.xetrasu.Rational.doubleValue(Rational.java:64)
        at com.xetrasu.Rational.doubleValue(Rational.java:64)
        at com.xetrasu.Rational.doubleValue(Rational.java:64)
        at com.xetrasu.Rational.doubleValue(Rational.java:64)
        at com.xetrasu.Rational.doubleValue(Rational.java:64)

Đây là mã nguồn của StackOverflowErrorOpenJDK 7


0

Trong tình trạng khủng hoảng, tình huống Dưới đây sẽ mang đến lỗi tràn Stack.

public class Example3 {

public static void main(String[] args) {

    main(new String[1]);

}

}


-1

Đây là một ví dụ

public static void main(String[] args) {
    System.out.println(add5(1));
}

public static int add5(int a) {
    return add5(a) + 5;
}

Về cơ bản, StackOverflowError là khi bạn cố gắng thực hiện một cái gì đó, rất có thể sẽ tự gọi nó và tiếp tục vô hạn (hoặc cho đến khi nó đưa ra StackOverflowError).

add5(a) sẽ tự gọi, và sau đó gọi lại, và cứ thế.


-1

Thuật ngữ "stack over tràn (tràn)" thường được sử dụng nhưng là một cách viết sai; các cuộc tấn công không tràn vào ngăn xếp mà là bộ đệm trên ngăn xếp.

- từ các slide bài giảng của Giáo sư Tiến sĩ Dieter Gollmann

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.