Bloomberg LP Interview Question
Software Engineer / DevelopersWhy cant one throw exception from destructor.
# If a destructor, called by the language runtime during stack unwinding, terminates
with an exception the whole program is terminated.
# It becomes difficult (some people say impossible) to design predictable (correct)
containers in the face of throwing destructors.
# Unspecified (and thus undefined) behavior of some parts of C++ language in the face
of throwing destructors.
# It is unpleasant to think about the fate of an object that happened to throw
from its destructor. In other words, what happens to the object for which the
destruction process has failed?
C++ exception handling:
The block of code you want to try starts with specifying the try command and surrounding the block with curly braces. Within this block, you can throw any occurring errors with the throw command. You must specify an error and this should be a class but we will get to this later. Immediately after the try-block is closed, the catch-block starts. Here the error handling code is placed. The following piece of pseudo code will show the idea:
try {
___...
___...
___throw Exception()
___...
___...
} catch( Exception e )
{
___...
___...
}
In this example, Exception is a defined class with a constructor with no parameters (as identified by the throw-call). It would be useful to have some info on what kind of error occurred. This could be done in two ways. We could define different exception-classes and throw them according to which error occurred. We also could give the class a parameter containing an error message and allow the class to display the message.
void g()
{
throw std::exception();
}
void f()
{
std::string str = "Hello"; // This string is newly allocated
g();
}
void main()
{
try
{
f();
}
catch(...)
{ }
}
The flow of the program:
* main() calls f()
* f() creates a local variable named str
* str constructor allocates a memory chunk to hold the string "Hello"
* f() calls g()
* g() throws an exception
* f() does not catch the exception.
Because the exception was not caught, we now need to exit f() in a clean fashion.
At this point, all the destructors of local variables previous to the throw
are called - This is called 'stack unwinding'.
* The destructor of str is called, which releases the memory occupied by it.
As you can see, the mechanism of 'stack unwinding' is essential to prevent resource leaks - without it, str would never be destroyed, and the memory it used would be lost forever.
* main() catches the exception
* The program continues.
The 'stack unwinding' guarantees destructors of local variables (stack variables) will be called when we leave its scope.
When exception occurs, interrupt is generated and control is transferred to the operating system. Operating System, in turn, calls the exception handler that inspects the function call sequence starting from the current function from where the exception originated, and performs its job of stack unwinding and control transfer. We can write our own exception handler and register it with the operating system that it would call in the event of an exception.
fork() is the name of the system call that the parent process uses to "divide" itself ("fork") into two identical processes. After calling fork(), the created child process is actually an exact copy of the parent - which would probably be of limited use - so it replaces itself with another process using the system call exec().
memory space contains a few different types of “objects” such as threads, manged object heaps, managed loader heap, native heaps, dll’s, and virtual allocations, so a good place to start is by running a performance monitor log with the following counters.
Process/Virtual Bytes
Process/Private Bytes
.net CLR Memory/# Bytes in all Heaps
.net CLR Memory/% Time in GC
.net CLR Memory/Large Object Heap size
.net CLR Loading/Bytes in Loader Heap
.net CLR Loading/Current Assemblies
The main thing to look for is if private bytes grow at approximately the same rate as virtual bytes and if # Bytes in all Heaps seem to follow the same curve.
If the private bytes keep increasing but # Bytes in all Heaps do not, you’re likely looking at a native memory leak (i.e. you are leaking in a COM component or similar) but if # Bytes in all heaps increase at the same rate as private bytes your leak is likely in managed code.
Much the same way, if you see a steady increase of virtual bytes but your private bytes stay pretty steady, your application probably has a problem where it is reserving a lot of virtual memory that it’s not using.
5) How is fork and exec different?
Processes can be created in 3 different ways. The first method is called forking . The second method is called exec . The difference between fork and exec is, that, when using exec, the process will not run as a separate, singular thread but within the other existing thread.
That means that this new thread shares the memory with the other thread. fork , in contrast, creates not only a new thread but also uses its own memory space and hence runs as a totally independ thread.
Ref:
www.codepedia.com/1/Inside-Linux
The exec functions of Unix-like operating systems are a collection of functions that causes the running process to be completely replaced by the program passed as argument to the function. As a new process is not created, the process ID (PID) does not change across and execute, but the data, heap and stack of the calling process are replaced by those of the new process.
1) Difference between delete and free.
- delete is used in C++ and it calls constructors to deallocate memory(earlier allocated by new)
- free deallocates memory in C which have been earlier allocated using malloc.
2) Why cant one throw exception from destructor.
- I believe you can throw exception from destructor (Dietel Deitel, p 793). and it can be caught by putting a try block around the function that calls the destructor.
3) How is exception handling implemented in C++
- examples above are correct.
3a)What is stack unwinding in exception handling.
- when an exception thrown is not caught in the current block (ex. a function), function call stack is unwound and an attempt is made to catch the exception in the next/outer try catch block (parent function).
10) What is memory leak and why.
-- if your program allocates memory but does not deallocate it once the program has run its course, it creates a memory leak. running the program enough times will make you run out of stack space.
11) What is auto-ptr and how is it implemented.
-- if an exception occurs after memory allocation, but before the delete statement executes, a memory leak could occur. auto_ptr is used to deal with this situation. when you leave the scope, auto_ptr automatically performs a delete on the object its pointing to.
auto_ptr<myClass> ptrToMyClass(new myClass);
ptrToMyClass->setValue(somevalue);
1)Objects created by new are destroyed by delete. Areas of memory allocated by malloc() are deallocated by free().
- CyberPhoenix November 20, 20072) Because the basic rules of the standard library and the language itself will be violated.
3) class Vector {
int sz;
int* elem;
class Range_error { };
public:
Vector(int s) : sz(s) { if (sz<0) throw Range_error(); /* ... */ }
// ...
};
3a) When an exception is thrown and control passes from a try block to a handler, the C++ run time calls destructors for all automatic objects constructed since the beginning of the try block. This process is called stack unwinding. The automatic objects are destroyed in reverse order of their construction.
11) An auto_ptr is an example of very simple handle class, defined in <memory>, supporting exception safety using the resource acquisition is initialization(RAII) technique. An auto_ptr holds a pointer, can be used as a pointer, and deletes the object pointed to at the end of its scope. For example:
#include<memory>
using namespace std;
struct X {
int m;
// ..
};
void f()
{
auto_ptr<X> p(new X);
X* q = new X;
p->m++; // use p just like a pointer
q->m++;
// ...
delete q;
}