The following two samples are real-world questions we've recently resolved. They are excellent examples, as they demonstrate that our abilities run the gamut from straightforward explanations to complex efficiency concerns.
Compiler Error Messages
By far the most common type of question is to explain compiler error messages. These are cases where a developer might waste an hour trying to decipher an error, when all that is needed is a second set of eyes. A question we recently answered involved the following snippet of code.
#include
static vector some_ints;
To which the compiler gave the error 'vector' : undeclared identifier, type 'int' unexpected.
Our staff immediately noticed that the developer had forgotten a using directive:
Since the compiler message was less than obvious, by the time the client contacted us they had spent several hours trying to get their code to work. This time was inefficiently spent redesigning the system architecture, implementing their own vector class, and a ton of other things that are obviously not the proper solution. We were able to provide an answer and get them on their way in less than a minute.
Efficiency Concerns
As demonstrated in this example, our expertise is in no way limited to straightforward error messages.
A client recently had concerns on the efficiency of C++ exceptions, he was interested in knowing the efficiency differences between allocating an exception on the stack vs. the heap. These cases are illustrated in the following snippet:
try
{
if( throwFromHeap() )
throw new AllocatedOnHeap;
else if( throwFromStack() )
}
catch( AllocateOnHeap * e ) { }
catch( AllocateOnStack & e ) { }
In the first case, the developer explicitly requests dynamic memory (with operator new) and must therefore spend the time required to access the heap. In the second case the developer is allocating memory on the stack, and then asking the compiler to pass the address to the catch block. However, the stack is supposed to be unwound as an exception is thrown, which seems to suggest that by the time the catch block is executed, the portion of the stack that was allocated to the exception will no longer exist!! It seems to be an example of a function that returns by reference an automatic variable.
This would suggest that it is only valid to throw exceptions indirectly, that is to say that every thrown exception requires dynamic memory. However, the second case seemed to work fine on both of the client's compilers (gnu 1.95 on linux and MS VisualC++ 6.0 on NT). What was happening?
GCC
We found that in the second case the gnu compiler actually inserts machine code to dynamically allocate memory and then copies the exception from the stack to the heap. It is this new exception that is actually thrown. The conclusion is that when using the gnu compiler it is better to just use the stack to begin with, and thus avoid the extra (and potentially expensive) copy operation.
Visual C++
The behaviour of the Microsoft compiler is much more interesting since it does not copy the exception to the heap. Instead of deallocating the stack when the exception is thrown, it just executes the destructors for all intervening automatic variables. This allows the catch block to use the portion of the stack where the exception was originally allocated. Once the catch block completes the MS compiler reclaims the entire stack. The conclusion is that when using the MS compiler it is more efficient to allocate the exception on the stack and thereby avoid expensive interaction with dynamic memory on the heap.
Summary
These are just two questions that we have answered recently. They were chosen to demonstrate that we have the ability to answer a wide range of questions.