When do we break binary compatibility

空扰寡人 提交于 2019-12-03 00:26:29

Breaking binary compatibility doesn't always result in the DLL not loading, in many cases you'll end up with memory corruption which may or may not be immediately obvious. It depends a lot on the specifics of what you've changed and how things were and now are laid out in memory.

Binary compatibility between DLLs is a complex subject. Lets start by looking at your three examples;

  • Add a new public virtual method virtual void aMethod();

This almost certainly will result in undefined behaviour, it's very much compiler dependant but most compilers will use some form of vtable for virtual methods, so adding new ones will change the layout of that table.

  • Add a new public non-virtual method void aMethod();

This is fine for a global function or a member function. A member function is essentially just a global function with a hidden 'this' argument. It doesn't change the memory layout of anything.

  • Implement a public pure-virtual method from an interface virtual void aMethod override;

This won't exactly cause any undefined behaviour but as you've found, it won't do what you expect. Code that was compiled against the previous version of the library won't know this function has been overridden, so will not call the new implementation, it'll carry on calling the old impl. This may or may not be a problem depending on your use case, it shouldn't cause any other side effects. However I think your mileage could vary here depending on what compiler you're using. So it's probably best to avoid this.

What will stop a DLL from being loaded is if you change the signature of an exported function in any way (including changing parameters and scope) or if you remove a function. As then the dynamic linker won't be able to find it. This only applies if the function in question is being used as the linker only imports functions that are referenced in the code.

There are also many more ways to break binary compatibility between dlls, which are beyond the scope of this answer. In my experience they usually follow a theme of changing the size or layout of something in memory.

Edit: I just remembered that there is an excellent article on the KDE Wiki on binary compatibility in C++ including a very good list of do's and don'ts with explanations and work arounds.

C++ doesn't say.

Visual Studio generally follows COM rules, allowing you to add virtual methods to the end of your most derived class unless they are overloads.

Any non-static data member will change the binary layout as well.

Non-virtual functions don't affect binary compatibility.

Templates make a huge mess because of name mangling.

Your best bet to retain binary compatibility is to use both the pimpl idiom and the nvi idiom quite liberally.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!