Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

A Reusable Directory Walk Class


May 1997/A Reusable Directory Walk Class/Sidebar

Microsoft vs. Borland Portability Woes


I developed DirWalk using the Microsoft Visual C++ 4.2 compiler, but late in the project, I decided to go for Borland compilability as well (using version 5.01). Getting there was not an insignificant task, as indicated by the #if defined(__BORLANDC__) and #if defined(_MSC_VER) conditional-compilation macros scattered throughout the source code.

The Borland and Microsoft compilers differ especially in their treatment of exception-handling. Borland requires you to be using the std namespace to declare any of the standard exception types from <stdexcept>, while Microsoft does not. You end up with this in files using standard exception types:

#if
defined(__BORLANDC__)
  using namespace std;
#endif

Concerning exception specifications, Microsoft's compiler complains if you try to include an exception specification on the declaration of a non-inline constructor, even though the definition of that constructor has an exception specification. Borland's implementation handles this case more gracefully, by forcing the exception specifications to match between declaration and definition. Thus, you'll see code like this in a header file:

class X { public:
#if defined(_MSC_VER)
    X(int x=0);
#else
    X(int x=0) throw();
#endif
};

And in the implementation file, just the one version of the definition:

X::X(int x) throw() {
...
}

Strangely, if you inline the constructor, then you can use the exception specification in the same way under both products.

Multithreading support is the other big area of compiler differences I ran into on this project. The preprocessor symbols indicating a multithreaded compile are different. This is no big deal, but still it would be nice if the two compilers could agree on a common symbol. As it stands, you'll see stuff like this in DirWalk:

#if defined(__BORLANDC__)
 #if defined(__MT__)
  #if !defined(_MT)
   #define _MT
  #endif
 #endif
#endif

Pretty, huh? It gets much worse.

Win32 has an API function CreateThread, which a program can use to create a separate thread of execution given the starting address of a function and some other data. But, in certain situations, each thread launched via CreateThread will produce small memory leaks [1] . To work around this problem, Microsoft and Borland have created their own functions to create threads. These functions both call CreateThread internally, and both clean up after the thread, but there the similarity just about ends. Here are the prototypes:

Win32:

HANDLE CreateThread(
    // pointer to thread security attributes
    LPSECURITY_ATTRIBUTES lpThreadAttributes,
    // initial thread stack size, in bytes
    DWORD dwStackSize,
    // pointer to thread function
    LPTHREAD_START_ROUTINE lpStartAddress,
    LPVOID lpParameter,  // argument for new thread
    DWORD dwCreationFlags, // creation flags
    LPDWORD lpThreadId  // pointer to returned thread identifier
    ;

Microsoft:

unsigned long _beginthreadex( void *security, unsigned stack_size,
         unsigned ( __stdcall *start_address )( void * ),
         void *arglist, unsigned initflag, unsigned *thrdaddr );

Borland:

unsigned long _beginthreadNT( void (_USERENTRY *start_address)(void *),
         unsigned stack_size, void *arglist, void *security_attrib,
         unsigned long create_flags, unsigned long *thread_id);

All three of these functions take essentially the same arguments, with the arguments to Borland's function having a different order for some reason. There are two principal differences between these functions. One difference is that CreateThread and _beginthreadNT take a pointer to an unsigned long for the thread ID, while _beginthreadex() takes a pointer to an unsigned int. But the most annoying difference is in the type of the function pointer that specifies the starting address of the new thread. The function passed to CreateThread must have this prototype:

DWORD WINAPI ThreadFunction(LPVOID ThreadParameter);

The function passed to _beginthreadex must have this prototype:

unsigned int WINAPI ThreadFunction(LPVOID ThreadParameter);

The function passed to _beginthreadNT() must have this prototype:

void ThreadFunction(LPVOID ThreadParameter);

So, not only must you redefine the calls to create the new thread, you must also redefine the thread function itself! (I would think that Microsoft would at least get agreement between the two functions for which it is responsible.) o

Note

[1] Specifically, if you're using the statically-linked multithreaded C runtime libraries, and if the thread calls certain C runtime functions that require a separate data area for each thread, memory leaks will occur. These functions include the errno-related functions, some time functions, strtok, tmpnam, tmpfile, and others.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.