Link to home
Start Free TrialLog in
Avatar of aphillips
aphillipsFlag for Australia

asked on

DLL backward compatiblity

We have a lot of software that uses several MFC extension DLLs.  It is an absolute maintenance nightmare now as these DLLs have been extended with no regard for backward compatibility.  So the latest DLL will probably not work with anything not built recently.  And if you try to rebuild a project you get all sorts of compile/link/runtime problems that can take days to resolve.

I have always argued that the DLLs should be kept backward compatible.  However, others (those who wrote them) say that you can't keep MFC extension DLLs backward compatible since as soon as you add a member everything moves around.  MS (usually) keep the MFC42.DLL backward compatible, so I believe this is wrong.

Even then the code could be kept compatible so that only a rebuild is necessary.  A common thing is for functions parameters to be changed or even removed or (more subtly) the behaviour "improved".  Why can't parameters be kept the same (perhaps with extra ones with appropriate default parameters).  If a major change is necessary then add a new function but don't change the behaviour of the old one.

I don't see that there is any inherent problem with DLLs, meaning that they cannot be kept backward compatible.  However, experience has shown that our programmers have a major problem doing so.  Perhaps using static libraries instead would alleviate this problem.

I was wondering how others address this.
Avatar of ambience
ambience
Flag of Pakistan image

>> MS (usually) keep the MFC42.DLL backward compatible, so I believe this is wrong.

You are in fact right in believing so, but look at the amount of effort they invest for backward compatibility, just realize that MFC42.dll exports thousands of function and all of them by fixed ordinal (mfc42.def). These are not ordinary names but mangled names, and it definitely requires efforts to export c++ API that way. Though i'm pretty sure there must be tools automating most of the process.


>> since as soon as you add a member everything moves around.

Thats ALMOST true, depends upon the way you are exporting symbols, normally programmers would export c++ symbols by using __declspec(dllexport) qualifiers, this is a very easy way to export symbols but you have no control over the way symbols are exported. Because each time you add methods the compiler is free to generate new ordinals for existing symbols. But what effect can it have on dll compatibility ??


>> MS (usually) keep the MFC42.DLL backward compatible, so I believe this is wrong

Because they never make any changes to function signatures (interface) after a release is made. Any major modifications result in change of dll version and a new iterface is provided with new ordinals. The rule is dont ever mess with existing export symbols !!! ....

>> Why can't parameters be kept the same (perhaps with extra ones with appropriate default parameters).  

Cahnging a paramter changes the signature and the mangled name for the exported function and since you are not linking thru ordinals this will definitely break the contract. Even with ordinal exports you dare not add remove or change the parameters that would break the contract at binary level (thats even more evil).

So the point is donot mess with existing interfaces. For structs and classes take extra care to not to effect the object layout (data members) and virtual tables etc.

I hope this helped ...




Avatar of aphillips

ASKER

Thinking back my original question was a bit vague.  There are really 3 situations:

(1) DLLs are kept "binary" compatible.
(2) DLLs are kept source code compatible.
(3) DLLs require code changes

Binary Compatible

By (1) I mean that all existing functions retain the same ordinal number.  An old program can use a new DLL as all the expected functions are there.  (A new program may not be able to use an older DLL.)

I suspect this is hard to do (but MFC42.DLL does it).  Is it only necessary to preserve the (mangled) name or do you need to preserve ordinals.  How are member functions mapped to ordinal numbers?  If a member function is added does this mess up the ordinal number for this and other classes?

How hard is keeping binary compatibility really?


Source Compatible

By (2) I mean when the code is changed it is just a matter of rebuilding (compiling with new headers and linking with new stub libs).

This should be easy to accomplish - any additions only extend existing interfaces by adding new member functions or defaulted parameters to existing functions.

But is this a good idea?  I believe that under some versions of Windows you can't have 2 DLLs in memory with the same name.  In which case you have to invent a version number system for the DLLs.  However, since our DLLs change weekly if not daily this is not really practical.

Under Windows 2000/XP you can keep the DLLs with the .EXE and it will use that DLL.  Ie, you can have different DLLs with the same name in memory.  But if you are going to have the DLLs in the same directory as the .EXE then why use dynamic linking at all, particularly with the abovementioned problems with earlier versions of Windows.

Unless I am missing something, if you are only supporting source compatibility then it is better to link statically and not use DLLs at all.


Code Changes

By (3) I mean that changes to the DLLs requires changes to the source code that uses them (new parameters, changed behaviour etc).  I can see no reason for doing this.

I think it happens in our environment because someone works out a better way to achieve the same thing (which requires different behaviour of the calling code).  The old code is commented out (or just edited) and replaced with the new code.

I guess people don't want to have old (redundant) code laying around.  But I think that old code should be left and new functions or classes added if their behaviour is different.

Superceded code may add to the bloat of a DLL, but if static linking was used then the code can be excluded from the .EXE if no longer used.


Conclusion

In summary my questions are:

a. Do you have this sort of problem?  If not why not?
b. If so, do you use DLLs or is keeping binary compatibility too hard?
c. Is static linking the best way to go?
d. Is there a better way or something I have missed?


Thanks ambience for your response in which you wrote:
> ... MFC42.dll exports thousands of function and all of them by fixed ordinal ...

But is this necessary?

> Changing a parameter changes the signature ...

OK, you can't add extra (defaulted) parameters but you could add an overridden function with the extra parameter.
ASKER CERTIFIED SOLUTION
Avatar of ambience
ambience
Flag of Pakistan image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
This probably should have been in a discussion forum since the question is general and there is no simple or specific answer.  But I didn't want to delete it as there is useful information that should be kept so I accepted the last reply as the answer.