I took a look at the draft C++0x standard, and as far as I can tell there is nothing about stack overflow in there. Searching for "stack overflow" yields no results, and searching for "stack" I've only gotten references to stack unwinding and std::stack. Does that mean that there cannot be a conforming implementation of the C++ standard, since there is no mechanism allowed for handling the error when memory is exhausted by a local object such as a huge local array?
The answers to this question indicate that at least the C standard does not mention stack overflow.
To make the question concrete, consider this program
// Program A
int identity(int a) {
if (a == 0)
return 0;
char hugeArray[1024 * 1024 * 1024]; // 1 GB
return identity(a - 1) + 1;
}
int main() {
return f(1024 * 1024 * 1024);
}
and this program
开发者_开发问答// program B
int main() {
return 1024 * 1024 * 1024;
}
I think the C++ standard does not allow any C++ implementation to do something observably different on these two programs. In reality program A won't run on any modern machine as it is allocating an exabyte of memory on the stack (imagine the function actually used the huge array so the compiler can't silently remove it to no ill effect). Does the C++ standard allow program A to fail?
Edit: The question is not whether the standard should define what happens on stack overflow, the question is what it says, if anything.
I'm not sure if this is what you're looking for, but in Appendix B of the C++03 ISO standard there's the following notice:
- Because computers are finite, C++ implementations are inevitably limited in the size of the programs they can successfully process. Every implementation shall document those limitations where known. This documentation may cite fixed limits where they exist, say how to compute variable limits as a function of available resources, or say that fixed limits do not exist or are unknown.
- The limits may constrain quantities that include those described below or others.
(My emphasis) I take this to mean it is perfectly legal for the compiler to allow one of those functions to work while failing another, provided that the compiler states what limitations are in place and how they are computed from the resources the system has available.
Behavior is undefined because the Standard does not define what happens with a program that exceeds resource limits. Note that there are recommended limits in Annex B of the spec. That annex is non-normative though and an implementation can ignore that annex, including having different limits than specified there. In 1.4 [intro.compliance], the spec says
If a program contains no violations of the rules in this International Standard, a conforming implementation shall, within its resource limits, accept and correctly execute that program.
There is nothing that says what shall happen with a program that contains no violation of the rules in the IS but that can't be accepted and correctly executed within the resource limits of the implementation. Hence behavior is undefined for such a case.
A stack overflow is breaking the protection mechanism that the operating system has in place. It is not a feature of the language as all machine executable code will have this same protection.
If you want to catch this particular error, you'll need to write operating system specific code. On Linux, for example, you'll need to catch a SIGSEGV (segmentation fault) signal. However, note that this could also be raised by a NULL pointer deference, or any other memory protection issues, not just stack overflow.
Not sure about Windows, OSX or mobile devices.
What happens on stack overflow is extremely system-dependent (both CPU and OS, and sometimes compiler because it's up to the compiler to insert stack probes and other mechanisms for safely extending the stack), so it's impossible to mandate a particular response; the best that could be done would be to suggest responses that would be preferable if the target platform allows it. Most don't; while there is a reasonable way to handle heap overflow, a stack overflow handler (a) is likely to be invoked when the stack is in an inconsistent state, with a partially constructed stack frame on it, and (b) is likely to involve invoking a handler... which requires stack space for the interrupt frame. POSIX specifies a sigaltstack()
mechanism, but it too has restrictions, and ANSI C C/C++ can't reasonably depend on POSIX compliance.
精彩评论