Skip to main content

Posts

Showing posts from April, 2008

19. What is a multi-threaded apartment (MTA)? Single-threaded apartment (STA)?

This is pretty difficult question to describe shortly. Anyway, apartments were introduced by Microsoft in NT 3.51 and late Windows 95 to isolate the problem of running legacy non-thread safe code into multithreaded environment. Each thread was “encapsulated” into so called single-threaded apartment. The reason to create an object in apartment is thread-safety. COM is responsible synchronize access to the object even if the object inside of the apartment is not thread-safe. Multithreaded apartments (MTA, or free threading apartment) were introduced in NT 4.0. Idea behind MTA is that COM is not responsible to synchronize object calls between threads. In MTA the developer is responsible for that. See “Professional DCOM Programming” of Dr. Grimes et al. or “Essential COM” of Don Box for the further discussion on this topic.

19. What is a multi-threaded apartment (MTA)? Single-threaded apartment (STA)?

This is pretty difficult question to describe shortly. Anyway, apartments were introduced by Microsoft in NT 3.51 and late Windows 95 to isolate the problem of running legacy non-thread safe code into multithreaded environment. Each thread was “encapsulated” into so called single-threaded apartment. The reason to create an object in apartment is thread-safety. COM is responsible synchronize access to the object even if the object inside of the apartment is not thread-safe. Multithreaded apartments (MTA, or free threading apartment) were introduced in NT 4.0. Idea behind MTA is that COM is not responsible to synchronize object calls between threads. In MTA the developer is responsible for that. See “Professional DCOM Programming” of Dr. Grimes et al. or “Essential COM” of Don Box for the further discussion on this topic.

Explain Synchronization with Mutex, Events, Semaphores, Critical Sections.

Mutex can be owned by a single thread at a time. all other will wait till that thread owns. once released others can own and access the resources owned by first thread. Semaphores: Allows only a limited no. of threads to access protected resources. Multiple threads can own it at a time. Can have initial count and max count. Initially initial count is equal to max. as owns by a thread it is decremented, once it is zero, no more threads are allowed to access resources. Critical Sections: same as Mutex, can be owned by one thread at a time. can work withing process. while mutex can work across process. Events: if one wants to alert, threads of some action is occuring. SetEvent is called to signal a state to all the threads waiting for it. PulseEvent used to quickly set-reset signalse. These can be autoreset or manual reset events. if manualreset =fasle( auto) will created and call setevent and changed to non signaled state. if initialstate =true created and sets to signaled state

Explain multi-threading..

by mulit threading many things can be done at once. windows time slices the cpu time and allocates to each thread. on expiring the time slice, thread is paused. the state( CPU Registers and other data) of the thread is saved. Another threading waiting for its slice will started. paused as above. when it comes to the first threads time its is reloaded and resumed. Can have base and dynamic priorities. base can be changed but not more than parent. dynamic is same as base except can be raised or lowered by windows. OS(win) chooses which thread to run next based on dynamic priority. Every programm has a primary thread can be used to create other thread. These objects are created by windows ojbect manager.

What are the advantages of polymorphism and dynamic binding?

They allow old code to call new code in a substitutable fashion. The real power of object-oriented programming isn't just inheritance; it's the ability to treat objects of derived classes as if they were objects of the base class. The mechanisms that support this are polymorphism and dynamic binding. Polymorphism allows an object of a derived class to be passed to a function that accepts a reference or a pointer to a base class. A function that receives such objects is a polymorphic function. When a polymorphic function invokes a member function using a base class reference or pointer, dynamic binding executes the code from the derived class even though the polymorphic function may be unaware that the derived class exists. The code that is executed depends on the type of the object rather than on the type of the reference or pointer. In this way, objects of a derived class can be substituted for objects of a base class without requiring any changes in the polymorphic functions

What is the purpose of inheritance?

In C++, inheritance is for subtyping. It lets developers model the kind-of relationship. Inheritance allows developers to make one class a kind-of another class. In an inheritance relationship, the new class is called the derived class and the original class from which the new class is being derived is called the base class. All the data structures and member functions that belong to the base class automatically become part of the derived class. For example, suppose the class Stack has member functions push() and pop(), and there is a need for a class PrintableStack. PrintableStack is exactly like Stack except PrintableStack also provides the member function print(). Class PrintableStack can be built by inheriting from Stack—Stack would be the base class and PrintableStack would be the derived class. The member functions push() and pop() and any others that belong to Stack automatically become part of PrintableStack, so the only requirement for building PrintableStack is adding the pri

What is the purpose of composition?

Composition allows software to be developed by assembling existing components rather than crafting new ones. Composition (sometimes called aggregation) is the process of putting an object (a part) inside another object (the composite). It models the has-a relationship. For example, a FordTaurus can be composed of, among other things, an Engine, Transmission, InstrumentPanel, and so on. In other words, a FordTaurus has an Engine (equivalently, an Engine is part-of a FordTaurus):

Explain use of Private Inheritance

The use of public inheritance implies an is-a relationship between a base class and its descendant. Unlike public inheritance, private inheritance is used when you want to inherit the implementation of the base class without the is-a commitment. Thus, if A is a non-public base of B, B has access to all the non-private members of A, but it's not an A. In this regard, private inheritance is almost identical to containment. When should you use private inheritance? Suppose you want to create a collection of objects of a certain type while reusing the functionality of another container class, say, Stack. You don't want your derived class D to behave as a Stack, you simply need the implementation of the Stack class. In this case, you privately derive D from Stack: class Stack { public: void push(Element &); void pop(); } class B: private Stack { public: int insert(const Element & e) { push(e); // reuse Stack::push } }; Note that the use of private inheritance allows yo

Dfference between delete and delete[]

There's a common myth among Visual C++ programmers that it's OK to use delete instead of delete [] to release arrays built-in types. For example, int *p = new int[10]; delete p; // very bad; should be: delete[] p This is totally wrong. The C++ standard specifically says that using delete to release dynamically allocated arrays of any type—including built-in types—yields undefined behavior. The fact that on some platforms apps that use delete instead of delete [] don't crash can be attributed to sheer luck: Visual C++, for example, implements both delete and delete [] for built-in types by calling free(). However, there is no guarantee that future releases of Visual C++ will adhere to this convention. Furthermore, there's no guarantees that this will work with other compilers. To conclude, using delete instead of delete[] and vice versa is a very bad programming habit that should be avoided.

the Differences Between static_cast and reinterpret_cast

The operators static_cast and reinterpret_cast are similar: they both convert an object to an object of a different type. However, they aren't interchangeable. Static_cast uses the type information available at compile time to perform the conversion, making the necessary adjustments between the source and target types. Thus, its operation is relatively safe. On the other hand, reinterpret_cast simply reinterprets the bit pattern of a given object without changing its binary representation. To show the difference between the two, let's look at the following example: int n = 9; double d = static_cast < double > (n); In this example, we convert an int to a double. The binary representation of these types is very different. In order to convert the int 9 to a double, static_cast needs to properly pad the additional bytes of d. As expected, the result of the conversion is 9.0. Now let's see how reinterpret_cast behaves in this context: int n = 9; double d = reinterp

the Difference Between Postfix and Prefix Operators

The built-in ++ and—operators can appear on both sides of their operand: int n=0; ++n; // prefix ++ n++; // postfix ++ You probably know that a prefix operator first changes its operand before taking its value. For example: int n=0, m=0; n = ++m; // first increment m, then assign its value to n cout << n << m; // display 1 1 In this example, n equals 1 after the assignment because the increment operation took place before m's value was taken and assigned to n. By contrast, int n=0, m=0; n = m++; // first assign m's value to n, then increment m cout << n << m; // display 0 1 In this example, n equals 0 after the assignment because the increment operation took place after m's original value was taken and assigned to n. To understand the difference between postfix and prefix operators better, you can examine the disassembly code generated for these operations. Even if you're not familiar with assembly languages, you can immediately see the differenc

What's the difference between aggregation and containment?

, in terms of C++ (to be precise in terms of UML) there is NO diference between aggregation and containment. Aggregation IS containment and containment IS aggregation. There is a difference, however, between aggregation and composition. This question should sound: "What's the difference between aggregation and composition in terms of UML?". Back to answer. The difference between aggregation and composition is life term of participating objects. Aggregated object can exist without container. Composited object is managed by it's container and cannot live without it. Interviewer would probably expect that you will say that composition implemented by creating object by value and aggregation implemented by creating object by reference (or pointer), but strictly saying it's not true. The true difference is who manages the life cycle of the aggregated object.

What is the difference between list and vector?

There are few differences: list and vector implement fundamentally different data structures. The major difference is the way of element access. Vector elements may accessed randomly while list elements must be accessed sequentially. Iterators are different as a result of the first item: list support bi-directional iterators while vector uses random access iterator. Some methods are difference (for example, only list supports merge and splice, adds push_front and pop_front etc.

What are the advantages of templates in C++?

Templates have several advantages. Firstly, they allow to avoid inappropriate multiple inheritance, where one of the inherited classes is just type to be managed. Secondly, they allow to inherit from "unknown" type, therefore creating "management" class for unknown type. Thirdly, templates allow to create "general" classes that is especially useful for all kind of type-safe collection classes. One good use is building framework classes that unite and hide several internal implementation classes (which can be non-template). This makes it easy for a beginner to use a big integrated complex functional class and still allows advanced users to rewrite portions of actual implementation.

• Why might you need exception handling be used in the constructor when memory allocation is involved?

Your first reaction should be: "Never use memory allocation in the constructor." Create a separate initialization function to do the job. You cannot return from the constructor and this is the reason you may have to use exception handling mechanism to process the memory allocation errors. You should clean up whatever objects and memory allocations you have made prior to throwing the exception, but throwing an exception from constructor may be tricky, because memory has already been allocated and there is no simple way to clean up the memory within the constructor.

• What are the advantage and disadvantage of using exception handling?

Disadvantage is a slight overhead imposed by implementing of exception handling mechanism. Advantage is "bullet-proof" program. With exception handling you have a mechanism which guarantee you control over program behavior despite the errors that might be in your program. With try-catch block you control not even given block of the program, but also all underlying function calls.

What’s the difference between COM and DCOM?

Again, the question does not require strict answer. Any DCOM object is yet a COM object (DCOM extends COM) and any COM object may participate in DCOM transactions. DCOM introduced several improvements/optimizations for distributed environment, such as MULTI_QI (multiple QueryInterface()), security contexts etc. DCOM demonstrated importance of surrogate process (you cannot run in-proc server on a remote machine. You need a surrogate process to do that.) DCOM introduced a load balancing.

10. What’s the difference, if any, between OLE and COM?

OLE is build on top of COM. The question is not strict, because OLE was built over COM for years, while COM as a technology was presented by Microsoft a few years ago. You may mention also that COM is a specification, while OLE is a particular implementation of this specification, which in today’s world is not exactly true as well, because what people call COM today is likely implementation of COM spec by Microsoft.

What is a moniker ?

An object that implements the IMoniker interface. A moniker acts as a name that uniquely identifies a COM object. In the same way that a path identifies a file in the file system, a moniker identifies a COM object in the directory namespace.

7. What is aggregation? How can we get an interface of the aggregated object?

Aggregation is the reuse mechanism, in which the outer object exposes interfaces from the inner object as if they were implemented on the outer object itself. This is useful when the outer object would always delegate every call to one of its interfaces to the same interface in the inner object. Aggregation is actually a specialized case of containment/delegation, and is available as a convenience to avoid extra implementation overhead in the outer object in these cases. We can get a pointer to the inner interface, calling QueryInterface of the outer object with IID of the inner interface.

4. How can would you create an instance of the object in COM?

, it all depends on your project. Start your answer from CoCreateInstance or CoCreateInstanceEx, explain the difference between them. If interviewer is still not satisfied, you’ll have to explain the whole kitchen behind the scenes, including a difference between local server and inproc server, meaning and mechanism of class factory, etc. You may also mention other methods of object creation like CoGetInstanceFromFile, but discussion will likely turn to discussion of monikers then.

1. What is IUnknown? What methods are provided by IUnknown?

It is a generally good idea to have an answer for this question if you claim you know COM in your resume. Otherwise, you may consider your interview failed at this point. IUnknown is the base interface of COM. All other interfaces must derive directly or indirectly from IUnknown. There are three methods in that interface: AddRef, Release and QueryInterface.

How to make sure that a file is not included more than once while compiling code ?

A header file should begin and end with #include guards to guarantee that it's not #included more than once during the same compilation session. A typical #include guard looks as follows: // from stdlib.h #ifndef File_Name_InCluded// included for the first time? #define File_Name_InCluded // declarations, typedef's etc. #endif // close #include guard at the end of the file Inside the header file, you may insert function prototypes, structs declarations, #define macros, enum types, typedef's, class declarations, extern declarations of global objects, template classes and functions, constants, certain #pragma directives that control the compilation process and similar macro directives. Note, however, that a header file should never have definitions (except for macros and templates). In other words, you shouldn't implement functions and class member functions inside a header file (except for inline functions), nor should you create variables, arrays, and object or global

Explain GetMessage(), PeekMessage(), SendMessage(), PostMessage().

These all functions are related to messages and application message queue. Message - Windows programming is a event based programming. On occurring any event operating system notifies it to that specific application by placing event type message in that application's message queue. Further this message (event) is processed / handled by respective application. Message Queue - This is queue associated with each windows application where messages are posted for processing. GetMessage() function waits for a message to be placed in the queue before returning. This function continously seeks for message in a message queue. PeekMessage() function does not wait for a message to be placed in the queue before returning. This is used to seek a specific message. PostMessage() function places (posts) a message in the message queue associated with the thread that created the specified window and then returns without waiting for the thread to process the message. SendMessage() function sends t

What is threading ?

A thread is basically a path of execution through a program. It is also the smallest unit of execution. A thread consists of a stack, the state of the CPU registers, and an entry in the execution list of the system scheduler. Each thread can shares all the process's resources. A process consists of 1. one or more threads 2. the code, 3. data, 4. other resources of a program in memory. Ex. open files, semaphores, dynamically allocated memory. A program executes when the system scheduler gives one of its threads execution control. The scheduler determines which threads should run and when they should run. Threads of lower priority might have to wait while higher priority threads complete their tasks. On multiprocessor machines, the scheduler can move individual threads to different processors to balance the CPU load. Each thread in a process operates independently. Unless you make them visible to each other, the threads execute individually and are unaware of the other threads in a

Understanding the Difference Between Postfix and Prefix Operators

The built-in ++ and—operators can appear on both sides of their operand: int n=0; ++n; // prefix ++ n++; // postfix ++ You probably know that a prefix operator first changes its operand before taking its value. For example: int n=0, m=0; n = ++m; // first increment m, then assign its value to n cout << n << m; // display 1 1 In this example, n equals 1 after the assignment because the increment operation took place before m's value was taken and assigned to n. By contrast, int n=0, m=0; n = m++; // first assign m's value to n, then increment m cout << n << m; // display 0 1 In this example, n equals 0 after the assignment because the increment operation took place after m's original value was taken and assigned to n. To understand the difference between postfix and prefix operators better, you can examine the disassembly code generated for these operations. Even if you're not familiar with assembly languages, you can immediately see the differenc

Invoking a Function Through a fuction Pointer

When you call a function through a pointer to function, use that pointer as if it were the function itself, not a pointer. For example: #include char buff[10]; void (*pf) (char *, const char *); pf = strcpy; // take address of strcpy pf(buff, "hi"); // use pf as if it were the function itself

What is a NaN?

Due to hardware limitations and the finite nature of computer arithmetic, certain numeric values cannot be represented properly. These values include infinity, negative infinity, and so on. The limits of floating point arithmetic also cause certain bit patterns to be meaningless or illegal. Such values are collectively known as NaN (“not a number”) values. The ISO Standard recognizes two types of NaN values: a quiet NaN and a signaling NaN. The latter causes a hardware exception to be thrown if a NaN value is used in an expression. A quiet NaN doesn't generate such an exception. The Standard Library defines function templates that identify these values: #include using namespace std; double value1, value2; value1=numeric_limits ::quiet_NaN(); value2=numeric_limits ::signaling_NaN(); This distinction is useful because sometimes you don't need to generate an exception when a NaN is encountered. For example, when you are calculating and displaying a graph, you do not want to genera

What are the advantages of using DLL's? What are the different types of DLL's? What are the differences between a User DLL and an MFC Extension DLL?

You may mention the following advantages: 1. DLLs are run-time modular. DLL is loaded when the program needs it. 2. Used as a code sharing between executables. Types of dlls Extension, Regular and pure Win32 DLL (without MFC) Extension DLL -> supports a C++ interface, i.e. can export whole C++ classes and the client may construct objects from them. Extension DLL dynamically links to MFC DLLs (those which name starts with MFC??.DLL) and to be synchronous with the version it was developed for. Extension DLL is usually small (simple extension DLL might be around 10K) Regular DLL -> can be loaded by any Win32 environment (e.g. VB 5) Big restriction is that regular DLL may export only C-style functions. Regular DLLs are generally larger. When you build a regular DLL, you may choose a static link (in this case MFC library code is copied to your DLL) and dynamic (in this case you would need MFC DLLs to be presented on the target machine)

What should you be aware of if you design a program that runs days/weeks/months/years?

When your program should run for a long time, you should be careful about heap allocations, because if you use new/delete intensively in your application, the memory becomes highly fragmented with a time. It is better to allocate all necessary memory in this case that many times small blocks. You should be especially careful about CString class which allocates permanent

How to handle command line arguements from simple MFC application ?

m_lpCmdLine Corresponds to the lpCmdLine parameter passed by Windows to WinMain. Points to a null-terminated string that specifies the command line for the application. Use m_lpCmdLine to access any command-line arguments the user entered when the application was started. m_lpCmdLine is a public variable of type LPTSTR. Code ex. BOOL CMyApp::InitInstance() { // ... if (m_lpCmdLine[0] == _T('\0')) { // Create a new (empty) document. OnFileNew(); } else { // Open a file passed as the first command line parameter. OpenDocumentFile(m_lpCmdLine); } // ... }

What is CArchive class does?

This class helps to do the serialization and de-serialisation. storing of objects from and to disk storage. The CArchive class allows user to save a complex objects to the permanent storage (usually disk storage) binary format. This objects persists after those objects are deleted. Later you can load the objects from permanent storage, reconstituting them in memory. This process of making data persistent is called “serialization.”

what is the use of AFX_MANAGE_STATE ?

By default, MFC uses the resource handle of the main application to load the resource template. If you have an exported function in a DLL, such as one that launches a dialog box in the DLL, this template is actually stored in the DLL module. You need to switch the module state for the correct handle to be used. You can do this by adding the following code to the beginning of the function: AFX_MANAGE_STATE(AfxGetStaticModuleState( )); This swaps the current module state with the state returned from AfxGetStaticModuleState until the end of the current scope. If all your resources lies in the single DLL you can even change the default handle to the DLL handle with the help of AfxSetResourceHandle function.

What Is CMutex ?

An object of class CMutex represents a “mutex” — a synchronization object that allows one thread mutually exclusive access to a resource. Mutexes are useful when only one thread at a time can be allowed to modify data or some other controlled resource. For example, adding nodes to a linked list is a process that should only be allowed by one thread at a time. By using a CMutex object to control the linked list, only one thread at a time can gain access to the list. To use a CMutex object, construct the CMutex object when it is needed. Specify the name of the mutex you wish to wait on, and that your application should initially own it. You can then access the mutex when the constructor returns. Call CSyncObject::Unlock when you are done accessing the controlled resource. An alternative method for using CMutex objects is to add a variable of type CMutex as a data member to the class you wish to control. During construction of the controlled object, call the constructor of the CMutex data

What You Should Include in a Header File

A header file should begin and end with #include guards to guarantee that it's not #included more than once during the same compilation session. A typical #include guard looks as follows: // from stdlib.h #ifndef STDLIB_INCLUDED // included for the first time? #define STDLIB_INCLUDED // declarations, typedef's etc. #endif // close #include guard at the end of the file Inside the header file, you may insert function prototypes, structs declarations, #define macros, enum types, typedef's, class declarations, extern declarations of global objects, template classes and functions, constants, certain #pragma directives that control the compilation process and similar macro directives. Note, however, that a header file should never have definitions (except for macros and templates). In other words, you shouldn't implement functions and class member functions inside a header file (except for inline functions), nor should you create variables, arrays, and object or global varia

How to Killi an Object Prematurely..

Sometimes, you need to force an object to destroy itself because its destructor performs an operation needed immediately. For example, when you want to release a mutex or close a file: void func(Modem& modem) { Mutex mtx(modem); // lock modem Dial("1234567"); /* at this point, you want to release the modem lock by invoking Mutex's dtor */ do_other_stuff(); //modem is still locked } //Mutex dtor called here After the function Dial() has finished, the modem no longer needs to be locked. However, the Mutex object will release it only when func() exits, and in the meantime, other users will not be able to use the modem. Before you suggest to invoke the destructor explicitly, remember that the destructor will be called once again when func() exits, with undefined behavior: void func(Modem& modem) { Mutex mtx(modem); // lock modem Dial("1234567"); mtx->~Mutex(); // very bad idea! do_other_stuff(); } //Mutex dto

Explain Virtual Destructors

Some classes in the Standard Library do not have a virtual destructor or virtual member functions by design. These classes include std::string, std::complex, and all STL containers. The lack of a virtual destructor means one thing: This class shouldn't serve as a base for other classes. Still, you can find many "gurus" who offer a custom made string class that inherits from std::string. To see how dangerous such an illicitly-derived class can be, consider the following program: #include #include using namespace std; int destr = 0; // destructor call counter class Derived: public string // bad idea { public: ~ Derived() { --destr;} }; int main() { string * p = new Derived; //...use p delete p; // undefined behavior cout>> destr >>endl; // surprise! n is still 0 } Class Derived publicly inherits from std::string. The global variable destr is initialized to 0. Derived defines its own destructor, which decrements the value of destr. Inside main(), the pr