below is a small C++-program that apparently gets aborted in a number of cases before "new" throws an exception:
int main(){
try{
while(true)
new char[2];
}
catch(...){
while(true);
}
}
The program was first compiled with MinGW/g++ 4.6.1 and then executed on a 32-bit Windows 7 system via the shell. No serious other programs (in terms of memory/CPU consumption) were running at the time. The program terminated before entering the catch-block. When compiling and running the program under Linux (Debian 7.3, gcc/c++ 4.7.2, 24GB memory) the program behaved similarly. (The reason for the infinite loop in the catch-block is to avoid anything there that might throw exceptions - particularly I/O.)
Something surprising (to me at least) happened when launching the program twice on the Windows system: If the program was launched in two different shells (almost) simultaneously, then neither of the two processes terminated before a new-exception was thrown.
Also unexpected to me was the observation that only a moderate enlargement of the size of the allocated chunks of memory (by replacing "2" in the fourth line with "9") made the premature termination disappear on the Windows system. On the Linux machine a much more drastic enlargement was needed to avoid the termination: approx. 40,000,000 bytes per block were necessary to prevent termination.
What am I missing here? Is this normal/intended behavior of the involved operating systems? And if so, doesn't this undermine the usefulness of exceptions - at least in the case of dynamic allocation failure? Can the OS settings be modified somehow (by the user) to prevent such premature terminations? And finally, regarding "serious" applications: At what point (w.r. to dynamic memory allocation) do I have to fear my application getting abruptly aborted by the OS?
Is this normal/intended behavior of the involved operating systems?
Yes, it's known as "overcommit" or "lazy allocation". Linux (and I think Windows, but I never program for that OS) will allocate virtual memory to the process when you request it, but won't try to allocate physical memory until you access it. That's the point where, if there is no available RAM or swap space, the program will fail. Or, in the case of Linux at least, other processes might be randomly killed so you can loot their memory.
Note that, when doing small allocations like this, the process will allocate larger lumps and place them in a heap; so the allocated memory will typically be accessed immediately. A large allocation will be allocated directly from the OS and so your test program won't access that memory - which is why you observed that the program didn't abort when you allocated large blocks.
And if so, doesn't this undermine the usefulness of exceptions - at least in the case of dynamic allocation failure?
Yes, it does rather.
Can the OS settings be modified somehow (by the user) to prevent such premature terminations?
On Linux, there's a system variable to control the overcommit policy:
echo 2 > /proc/sys/vm/overcommit_memory
The value 2 means to never overcommit - allocations will fail if they ask for more than the currently uncommitted RAM plus swap. 1 means to never fail an allocation. 0 (the default) means to guess whether an allocation request is reasonable.
I've no idea whether Windows is similarly configurable.
Related
So I recently got into learning C++ and I was really intrigued by memory allocation, garbage collection, heap, stack, etc...
I wrote this program, and I was wondering what it would do to my computer? Would it crash because my RAM would get filled up? Would it run slower? Would it stop before it fills up too much ram?
I am too afraid of running it on my machine.
#include <iostream>
using namespace std;
int main()
{
while (true) {
int* x = new int;
}
}
EDIT:
So I ran the program on my PC and it is really just a ram eating program. I kept it going until windows explorer failed and my desktop went black. Then I rebooted the PC and it was fine.
It actually depends on the host system on which the program is run, and the compiler.
Some compilers (particularly with optimisation settings enabled) are smart enough to recognize that that the memory allocated in the loop is not used in a way that affects program output. The compiler may then omit the memory allocation and may then (since an infinite loop that does nothing actually yields undefined behaviour in C++) do anything. Possible outcomes then include the program looping forever (consuming CPU cycles but not allocating memory), the compiler not generating the loop at all (so the program immediately terminates).
If compiler optimisation is not in play (e.g. a non-optimised build) the program may loop and repeatedly allocate memory. What happens then depends on the operating system.
Some operating systems - such as unix variants - can be configured (or are configured by default) to do lazy allocation or over-committing, in the sense they won't actually allocate virtual or physical memory until the program tries to non-trivially use that memory (e.g. stores data in it). Since your loop never uses the memory it allocates, on a system doing lazy allocation, the loop may run indefinitely - with no observable effect on the host system, other than lost CPU cycles.
If the OS is not configured to do lazy allocation (e.g. actually allocates the memory immediately) the loop will continue until allocation fails and terminate the program by throwing an exception.
What happens during that process depends, again, on the operating system.
If the operating system imposes a limited quota to the process that is significantly less than the total memory (physical or virtual) available to the operating system, then other processes (and the OS itself) may be unaffected by our program.
If the operating system allows the program to allocate all available memory, then the repeated allocation in this program may affect the behaviour of other programs, or the operating system itself. If the operating system is able to detect that, it may forceably terminate the program - and, in that process, it may reclaim the allocated memory. If the operating system does not detect that behaviour and terminate the program, the program may cause slow-down of the operating system.
If your operating system itself is hosted (e.g. in a hypervisor environment) then the operating system itself may be terminated, but other instances of operating systems running on the same physical machine will normally be unaffected.
It has been at least two decades since a novice programmer could unleash such a program on an unsuspecting machine, and be even a little confident that the machine will eventually slow down and possibly crash, or need a hard power cycle. Operating system design, and larger system designs (e.g. routine use of hypervisors) make such pranks less likely to have any enduring effect.
first thing you will face with is memory leak.
but your programme will continue to allocate memory from heap and will face with memory leak but OS will stop your programme. there is concept in OS named OOM. in this concept if some programme continue to allocate memory and cause some important part of system goes down OS will immediately send SIGKILL signal. which is cause you programme killed and then free allocated memory.
I'm trying to understand how the objects (variables, functions, structs, etc) work in c++. In this case I see there are basically two ways of storing them: the stack and the heap. Accordingly, whenever the heap storage is used it needs to be dealocated manually, but if the stack is used, then the dealocation is automaticcally done. so my question is related to the kinds of problems that bad practice might cause the program itself or to the computer. For example:
1.- Let'suposse that I run a program with a recursion solution by using an infinite iteration of functions. Theoretically the program crashes (stack overflow), but does it cause some trouble to the computer itself? (To the RAM maybe or to the SO).
2.- What happens if I forget to dealocate memory on the heap. I mean, does it just cause trouble to the program or it is permanent to the computer in general. I mean it might be that such memory could not be used never again or something.
3.- What are the problems of getting a segmentation fault (the heap).
Some other dangers or cares relevant to this are welcome.
Accordingly, whenever the stack storage is used it needs to be
dealocated manually, but if the heap is used, then the dealocation is
automaticcally done.
When you use stack - local variables in the function - they are deallocated automatically when the function ends (returns).
When you allocate from the heap, the memory allocated remains "in use" until it is freed. If you don't do that, your program, if it runes for long enough and keep allocating "stuff", will use all memory available to it, and eventually fail.
Note that "stackfault" is almost impossible to recover from in an application, because the stack is no longer usable when it's full, and most operations to "recover from error" will involve using SOME stack memory. The processor typically has a special trap to recover from stack fault, but that lands insise the operating system, and if the OS determines the application has run out of stack, it often shows no mercy at all - it just "kills" the application immediately.
1.- Let'suposse that I run a program with a recursion solution by using an infinite iteration of functions. Theoretically the program
crashes (stack overflow), but does it cause some trouble to the
computer itself? (To the RAM maybe or to the SO).
No, the computer itself is not harmed by this in and of itself. There may of course be data-loss if your program wasn't saving something that the user was working on.
Unless the hardware is very badly designed, it's very hard to write code that causes any harm to the computer, beyond loss of stored data (of course, if you write a program that fills the entire hard disk from the first to the last sector, your data will be overwritten with whatever your program fills the disk with - which may well cause the machine to not boot again until you have re-installed an operating system on the disk). But RAM and processors don't get damaged by bad coding (fortunately, as most programmers make mistakes now and again).
2.- What happens if I forget to dealocate memory on the heap. I mean, does it just cause trouble to the program or it is permanent to the
computer in general. I mean it might be that such memory could not be
used never again or something.
Once the program finishes (and most programs that use "too much memory" does terminate in some way or another, at some point).
Of course, how well the operating system and other applications handle "there is no memory at all available" varies a little bit. The operating system in itself is generally OK with it, but some drivers that are badly written may well crash, and thus cause your system to reboot if you are unlucky. Applications are more prone to crashing due to there not being enough memory, because allocations end up with NULL (zero) as the "returned address" when there is no memory available. Using address zero in a modern operating system will almost always lead to a "Segmentation fault" or similar problem (see below for more on that).
But these are extreme cases, most systems are set up such that one application gobbling all available memory will in itself fail before the rest of the system is impacted - not always, and it's certainly not guaranteed that the application "causing" the problem is the first one to be killed if the OS kills applications simply because they "eat a lot of memory". Linux does have a "Out of memory killer", which is a pretty drastic method to ensure the system can continue to work [by some definition of "work"].
3.- What are the problems of getting a segmentation fault (the heap).
Segmentation faults don't directly have anything to do with the heap. The term segmentation fault comes from older operating systems (Unix-style) that used "segments" of memory for different usages, and "Segmentation fault" was when the program went outside it's allocated segment. In modern systems, the memory is split into "pages" - typically 4KB each, but some processors have larger pages, and many modern processors support "large pages" of, for examble, 2MB or 1GB, which is used for large chunks of memory.
Now, if you use an address that points to a page that isn't there (or isn't "yours"), you get a segmentation fault. This, typically will end the application then and there. You can "trap" segmentation fault, but in all operating systems I'm aware of, it's not valid to try to continue from this "trap" - but you could for example store away some files to explain what happened and help troubleshoot the problem later, etc.
Firstly, your understanding of stack/heap allocations is backwards: stack-allocated data is automatically reclaimed when it goes out of scope. Dynamically-allocated data (data allocated with new or malloc), which is generally heap-allocated data, must be manually reclaimed with delete/free. However, you can use C++ destructors (RAII) to automatically reclaim dynamically-allocated resources.
Secondly, the 3 questions you ask have nothing to do with the C++ language, but rather they are only answerable with respect to the environment/operating system you run a C++ program in. Modern operating systems generally isolate processes so that a misbehaving process doesn't trample over OS memory or other running programs. In Linux, for example, each process has its own address space which is allocated by the kernel. If a misbehaving process attempts to write to a memory address outside of its allocated address space, the operating system will send a SIGSEGV (segmentation fault) which usually aborts the process. Older operating systems, such as MS-DOS, didn't have this protection, and so writing to an invalid pointer or triggering a stack overflow could potentially crash the whole operating system.
Likewise, with most mainstream modern operating systems (Linux/UNIX/Windows, etc.), memory leaks (data which is allocated dynamically but never reclaimed) only affect the process which allocated them. When the process terminates, all memory allocated by the process is reclaimed by the OS. But again, this is a feature of the operating system, and has nothing to do with the C++ language. There may be some older operating systems where leaked memory is never reclaimed, even by the OS.
1.- Let'suposse that I run a program with a recursion solution by using an infinite iteration of functions. Theoretically the program crashes (stack overflow), but does it cause some trouble to the computer itself? (To the RAM maybe or to the SO).
A stack overflow should not cause trouble neither to the Operating System nor to the computer. Any modern OS provides an isolated address space to each process. When a process tries to allocate more data in its stack than space is available, the OS detects it (usually via an exception) and terminates the process. This guarantees that no other processes are affected.
2.- What happens if I forget to dealocate memory on the heap. I mean, does it just cause trouble to the program or it is permanent to the computer in general. I mean it might be that such memory could not be used never again or something.
It depends on whether your program is a long running process or not, and the amount of data that you're failing to deallocate. In a long running process (e.g. a server) a recurrent memory leak can lead to thrashing: after some time, your process will be using so much memory that it won't fit in your physical memory. This is not a problem per se, because the OS provides virtual memory but the OS will spend more time moving memory pages from your physical memory to disk than doing useful work. This can affect other processes and it might slow down the system significantly (to the point that it might be better to reboot it).
3.- What are the problems of getting a segmentation fault (the heap).
A Segmentation Fault will crash your process. It's not directly related to the usage of the heap, but rather to accessing a memory region that does not belong to your process (because it's not part of its address space or because it was, but it was freed). Depending on what your process was doing, this can cause other problems: for instance, if the process was writing to a file when the crash happened it's very likely that it will end up corrupt.
First, stack means automatic memory and heap means manual memory. There are ways around both, but that's generally a more advanced question.
On modern operating systems, your application will crash but the operating system and machine as a whole will continue to function. There are of course exceptions to this rule, but they're (again) a more advanced topic.
Allocating from the heap and then not deallocating when you're done just means that your program is still considered to be using the memory even though you're not using it. If left unchecked, your program will fail to allocate memory (out of memory errors). How you handle out-of-memory errors could mean anything from a crash (unhandled error resulting in an unhandled exception or a NULL pointer being accessed and generating a segmentation fault) to odd behavior (caught exception or tested for NULL pointer but no special handling case) to nothing at all (properly handled).
On modern operating systems, the memory will be freed when your application exits.
A segmentation fault in the normal sense will simply crash your application. The operating system may immediately close file or socket handles. It may also perform a dump of your application's memory so that you can try to debug it posthumously with tools designed to do that (more advanced subject).
Alternatively, most (I think?) modern operating systems will use a special method of telling the program that it has done something bad. It is then up to the program's code to decide whether or not it can recover from that or perhaps add additional debug information for the operating system, or whatever really.
I suggest you look into auto pointers (also called smart pointers) for making your heap behave a little bit like a stack -- automatically deallocating memory when you're done using it. If you're using a modern compiler, see std::unique_ptr. If that type name can't be found, then look into the boost library (google). It's a little more advanced but highly valuable knowledge.
Hope this helps.
I am working on quite a large SIP telephony application and occasionally when we use the integrated web UI (written using tntnet) under heavy call load the program will exit due to a std::bad_alloc being thrown. There are hundreds of threads in use (3 per active call), so the location of the code causing the exception is quite random but is always after using the GUI.
Now, I understand that std::bad_alloc can be thrown when out of memory, which is not the case in this situation. I also am thinking that it can be thrown when there is heap corruption, which I am still looking for where ever it may be in the code base.
But my question is, are there any other reasons that std::bad_alloc will be thrown other than out of memory or heap corruption? I am using GNU g++ on Linux.
Most likely, you really are out of memory. It would be an extremely rare heap corruption bug that consistently caused only bad_alloc to be thrown. That would be like scribbling with surgical precision.
It is possible there's simply a bug in the code that allocates a massive amount of memory. But you would expect the exception to be thrown, at least a large fraction of the time, in that very code. The fact that the exception is coming from a number of different places weighs against that.
Severe fragmentation can cause a problem, particularly for platforms with poor implementations of malloc. That's rare, but it does happen.
One thing I'd do immediately -- catch the exception and call a function that saves a copy of /proc/self/maps. That will give you a good idea of the peak memory usage of the process. You can judge if it's anywhere near any platform, policy, or hardware limitations.
On linux the current Address Space limit can be used to artificially limit the amount of memory a process can use. You can manually set this with setrlimit(RLIMIT_AS, ...). This can also be set for an entire shell in bashrc using ulimit -v. This can also be set for the entire system in /etc/security/limits.conf. There might even be a /proc/sys entry for this someplace, I'm not sure.
If the address space limit is reached, your process will throw an std::bad_alloc when trying to allocate more memory. On a 64-bit system this can be a nice "safety" to make sure a bad application or library doesn't run away with the available memory and make the system go to swap or stop working altogether. Make sure the program doesn't set this itself someplace, and make sure the rest of the environment hasn't set it either. You can just insert some code in the middle of the program someplace to call getrlimit(RLIMIT_AS, ...) to be sure it hasn't snuck in someplace.
A perhaps more common cause (other than actually running out of memory, of course) is an unsigned integer wrap around case, where a uin32_t or uint64_t is used to allocate memory but was 0 and had 1 subtracted from it, leading to a very large request allocation (in 64-bits that would be many thousands of petabytes).
In any case, the best ways to track this down are with GDB. If your application doesn't use exceptions at all (and thus has no "catch" statements at all) then you can enable core files (ulimit -c unlimited). The next time the program crashes, the OS will generate a core file and loading it up in GDB will immediately give you a backtrace showing you where the program crashed.
If you have a few (but not many) places where try is used and its catching these bad allocs, other than just commenting them out while you debug this problem, you can run the application in GDB and use the catch throw command to have GDB break every time an exception is thrown. For either of these to work, never compile with -fomit-frame-pointer and always compile (even when using -O3) with -ggdb.
When a C++ program terminates, the RAM used during the run gets cleaned and is returned to the system, correct?
Question 1)
Is this memory returned managed by C++ language features or by the computer hardware itself?
Question 2)
Does the memory get returned efficiently/safely, if I terminate a run using ctrl+Z in Unix terminal?
When a C++ program terminates, the RAM used during the run gets cleaned and is returned to the system, correct?
Correct. By System, I hope you mean, Operating System.
Question 1) Is this memory returned managed by C++ language features or by the computer hardware itself?
The returned memory is managed by the operating system (if I correctly understand the question). And before returning to the OS, the memory is managed by the process; in low-level, which means, managed by various language features, such as allocation- deallocation mechanism, constructors, destructors, RAII, etc.
Question 2) Does the memory get returned efficiently/safely, if I terminate a run using ctrl+Z in Unix terminal?
Ctrl+Z suspends the process. It doesn't terminate it. So the memory doesn't get returned to the OS as long as the process is not terminated.
In linux, Ctrl+C terminates the process, then the memory returns to the OS.
Typically both. At least assuming normal termination, destructors will run, which will typically free the memory associated with those objects. Once your program exits, the OS will free all the memory that was owned by that process.
A forced termination often won't run the destructors and such, but any reasonable operating system is going to clean up after a process terminates, whether it did so cleanly or not. There are limits though, so if you've used things like lock files, it probably can't clean those up.
Q: When a C++ program terminates, the RAM used during the run gets
cleaned and is returned to the system, correct?
A: Correct. This is true for ANY program, regardless of the language it was written in, and regardless of whether it's Linux, Windows or another OS
Q Is this memory returned managed by C++ language features or by the
computer hardware itself?
A: Neither: the operating system is responsible for managing a process's memory.
Q: Does the memory get returned efficiently/safely, if I terminate a
run using ctrl+Z in Unix terminal?
A: OS resources (such as memory) are freed. But you can leave files corrupted, IPCs locked, and other Bad Things that are beyond the OS's control if you kill a program gracelessly.
'Hope that helps
Is this memory returned managed by C++ language features or by the computer hardware itself?
Both occur, assuming a proper shutdown (vs. a crash or kill). The standard C/C++ library deallocates any (non-leaked) memory it allocated via OS system calls and ultimately the OS cleans up any leaked memory.
Does the memory get returned efficiently/safely, if I terminate a run using ctrl+Z in Unix terminal?
Ctrl-Z suspends a process on Unix. If you terminate it using kill or kill -9, the memory will be reclaimed (safely / efficiently) by the OS.
They say that dynamically allocated memory is only returned by you, the programmer. For example, a
myclass *obj = new myclass();
always has to have a corresponding
delete obj;
somwehere, or else your program will leak memory, meaning the operating system could think that certain parts of memory are used when in fact they are not - after too many leaks your memory might be used up by false memory entirely and you won't be able to do anything with it.
However, "C++" (effectively meaning "the compiler") takes care of everything that you allocate on the stack, like
myclass obj;
as long as your destructors actually correctly deletes anything which you dynamically create inside that class.
In practice however, if you leak memory, modern operating systems will take care of it and usually clean it up. Usually there's some system in place where the OS will be able to recognize what parts of the memory you actually used, and then simply free everything in there as soon as the application is terminated.
Memory leaks usually only really create problems when your application needs so much memory that it needs to correctly free up some from time to time, or when you continuously leak memory in a loop (like in games), on systems with limited memory (like consoles).
I have a program that implements several heuristic search algorithms and several domains, designed to experimentally evaluate the various algorithms. The program is written in C++, built using the GNU toolchain, and run on a 64-bit Ubuntu system. When I run my experiments, I use bash's ulimit command to limit the amount of virtual memory the process can use, so that my test system does not start swapping.
Certain algorithm/test instance combinations hit the memory limit I have defined. Most of the time, the program throws an std::bad_alloc exception, which is printed by the default handler, at which point the program terminates. Occasionally, rather than this happening, the program simply segfaults.
Why does my program occasionally segfault when out of memory, rather than reporting an unhandled std::bad_alloc and terminating?
One reason might be that by default Linux overcommits memory. Requesting memory from the kernel appears to work alright, but later on when you actually start using the memory the kernel notices "Oh crap, I'm running out of memory", invokes the out-of-memory (OOM) killer which selects some victim process and kills it.
For a description of this behavior, see http://lwn.net/Articles/104185/
It could be some code using no-throw new and not checking the return value.
Or some code could be catching the exception and not handling it or rethrowing it.
What janneb said. In fact Linux by default never throws std::bad_alloc (or returns NULL from malloc()).