1

I tried to create large amount of memory in stack (int a[1000000000]). It compiled successfully. However at run time it Segfaulted. Its perfectly agreeable that the program segfaults. My question is, why cant the compiler detect this before hand and throw an compilation error? Why should we wait till the program runs?

Also, when i allocate int a[100], the asm code looks like following.

00000000004004b4 <main>:
  4004b4:       55                      push   %rbp
  4004b5:       48 89 e5                mov    %rsp,%rbp
  4004b8:       48 81 ec 18 01 00 00    sub    $0x118,%rsp (memory created for 100 bytes)

If i create for a large memory int a[1000000000], the asm code looks different.

00000000004004b4 <main>:
  4004b4:       55                      push   %rbp
  4004b5:       48 89 e5                mov    %rsp,%rbp
  4004b8:       49 bb 78 00 17 be 33    movabs $0xfffe9433be170078,%r11
  4004bf:       94 fe ff 
  4004c2:       4c 01 dc                add    %r11,%rsp

Can someone please explain this? i.e Why is not the compiler taking care of this?

4
  • 2
    How is the compiler supposed to know the amount of memory of the target? Commented Feb 27, 2014 at 22:29
  • I believe you have just gone beyond the Stack Segment. Commented Feb 27, 2014 at 22:30
  • 1
    How would the compiler know how much stack space will be available at run time? Commented Feb 27, 2014 at 22:31
  • 1
    If you have two questions then please post two questions. Do not post a single question with two questions; the second question is likely to be ignored. If it is not, it is hard to choose which is the accepted answer, should both questions be answered in separate answers. Commented Feb 27, 2014 at 23:29

4 Answers 4

9

why can't the compiler detect this beforehand and produce a compilation error or warning?

The question assumes an incorrect premise. There is very little technically stopping a compiler writer from doing so. You'd likely want it to be a warning and not an error, but a compiler writer could easily put a threshold on what is an unreasonably enormous size for the total amount of local storage used by a function and give a warning if that size is exceeded.

Since your question is based on a false premise it has no answer. Ask a better question.

OK, if it is possible then why do compiler writers not implement this warning?

Whether your compiler is open source or closed source, whether the people developing it are paid or volunteers, all changes to software require time and effort. Both are in short supply.

Compiler warnings are features and therefore must be designed, specified, implemented, tested, debugged, shipped and maintained. All of these things are expensive in both time and effort, and all of them remove time and effort from other features.

If this feature doesn't exist in a compiler that you like, it's because the developers of that compiler had approximately one million better things to do. Of those one million better things to do, this year they'll probably manage to implement a couple dozen. If you want to advocate for your particular feature suggestion to move up the list from its current low position, start calling up compiler developers and make your case to them that this is the best possible way they could be spending their effort -- on creating a warning for a condition that is obviously bogus and that will crash immediately. You will likely not get far.

When considering what compiler warnings to implement, compiler writers such as myself think hard about what warnings to add to compilers. Good warnings identify situations that are:

  • Legal; illegal code is of course an error.
  • Detectable with low false positive rate; a warning that instructs developers to change correct, working code into broken code is a bad warning
  • Misleading; said programmer should have a belief that the code does one thing when in fact it does another
  • Plausible; a programmer should be reasonably likely to type in the warned-about code in a line-of-business program
  • Undetectable by trivial testing; the program should run normally and do some subtly wrong thing. If the program crashes immediately then the warning is just finding the bug a few seconds before testing finds it, and that's not good value.

Your proposal meets the first two criteria. It arguably meets the third. It unambiguously fails to meet the fourth and fifth criteria. I would therefore reject your suggestion were I the compiler developer. I would spend my valuable time and effort adding features that were bigger benefit for the cost.

Sign up to request clarification or add additional context in comments.

Comments

4

Compiler is not responsible for stack allocation. The stack space for the binary is reserved by the linker. For example, ld has --stack option:

--stack reserve

--stack reserve,commit

   Specify the number of bytes of memory to reserve (and optionally commit)
   to be used as stack for this program.  The default is 2Mb reserved,
   4K committed.  [This option is specific to the i386 PE targeted
   port of the linker]

Additionally, the process may clone itself to create other processes/threads. At that point, whoever creates a clone controls how much memory to allocate for the stack and neither compiler not linker can help there.

And, finally, operating system may have other limitations on top of it. For example, Linux has soft and hard limit for stack size and won't allow any process to create its stack if it violates the limit set for the process. See ulimit.

In theory, it is possible for a compiler to analyze the program and try to estimate total stack usage and, say, hint the linker about how much it should try to reserve for a stack. However, this becomes very problematic if, for example, dynamic linking is used. Or, for instance, program has a recursion which depth depends on a run-time variable (i.e. some graph search algorithm). Then there is no way to do that. Given that implementing such a heuristic in a compiler is far from trivial, and the fact that most programs have some sort of recursion or dynamic linking, it is simply not worth the effort.

Comments

3

compiler can't be aware of all the target machine limitations

the compiler task is just to compile your code in the machine-code equivalent form for your CPU/architecture

have you ever seen a compiler complaining about too much memory allocated in the heap? :-)

compiler transcodes the high level program in the low level machine code equivalent

4 Comments

Thank you. I thought the compiler would know about the architecture for which the code would run
obviously it could be if programmed properly but it would not be just a compiler. A compiler just transcodes your high-level program into the corresponding low level machine representation. no more than that. What you want is well beyond syntax correctness
and more: let's imagine allocating in the stack a buffer which size is computed at runtime. How the compiler could possibly detect a stack overflow (!!! yeah, stackoverflow! ) just analyzing the static source code?
To illustrate, you can change the stack size with ulimit -s. If you set a 4gig stack by running ulimit -s 4294967296 (4gig stack) first, your program will run (assuming int on your system is 4 bytes).
1

This is to make it more compatible across machines with same arch but different specs.

Because the compiler can't predict the specs of the machine you'll be running your binary on. When you run a binary, it has to be similar arch (x86/ARM), but machines with same architectures can have varying specs for memory.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.