Add member variable to class in the shared library, will not break binary compatibility?
-
wrote on 31 Jul 2020, 02:33 last edited by
I had wanted to find an example to express my understanding of binary compatibility, but blown it. I want to change the layout of members of class in the DLL by add members to class at the beginning or in the middle, and expect that the variable cannot be accessed correctly or accessing the variable will generate crash.However, everything goes well. I find, no matter how I add member variable to any position of class,there are no crash and not breaking binary compatibility. My code as following:
//untitled1_global.h #include <QtCore/qglobal.h> #if defined(UNTITLED1_LIBRARY) # define UNTITLED1_EXPORT Q_DECL_EXPORT #else # define UNTITLED1_EXPORT Q_DECL_IMPORT #endif
//base.h class UNTITLED1_EXPORT Base { public: Base(); double getA(); double getB(); private: int arr[100]; //Add later to update the DLL double a; double b; };
//derived.h #include "dpbase.h" class UNTITLED1_EXPORT Derived : public Base { public: Derived(); void setC(double d); double getC(); private: char arrCh[100]; //Add later to update the DLL double c; };
Below is the client code,
base.h
、derived.h
included aren't same as in the DLL, one is annotated and one not. Implementation and declaration are separate in the DLL.I tried to access the variable directly and access the variable by funcation(such as annotated at the beginning ofmain.cpp
).//main.cpp #include "dpbase.h" #include "dpbase2.h" #include <QDebug> #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); Base base; qDebug() << base.getA(); qDebug() << base.getB(); Derived base2; base2.setC(50); qDebug() << base2.getC(); return a.exec(); }
Among them, class
Base
,Derived
is exported from dll.No matter how I add member variable to whetherBase
orDerived
anywhere,there are no crash and not breaking binary compatibility.I am using qt.There is a same question here, but no help for me.
Furthermore, I delete all member var of class in the DLL, I still use nonexistent variable in the client by linking the DLL,assign value, get it...It seems that there is enough space reserved in the dynamic library to be redefined by the client, even if no member variable is defined.So strange!
My question is, why changing the layout of members of class in the DLL, will not break binary compatibility?And deleting all member var of class in the DLL but why the caller can still use members in the .h file?
-
I had wanted to find an example to express my understanding of binary compatibility, but blown it. I want to change the layout of members of class in the DLL by add members to class at the beginning or in the middle, and expect that the variable cannot be accessed correctly or accessing the variable will generate crash.However, everything goes well. I find, no matter how I add member variable to any position of class,there are no crash and not breaking binary compatibility. My code as following:
//untitled1_global.h #include <QtCore/qglobal.h> #if defined(UNTITLED1_LIBRARY) # define UNTITLED1_EXPORT Q_DECL_EXPORT #else # define UNTITLED1_EXPORT Q_DECL_IMPORT #endif
//base.h class UNTITLED1_EXPORT Base { public: Base(); double getA(); double getB(); private: int arr[100]; //Add later to update the DLL double a; double b; };
//derived.h #include "dpbase.h" class UNTITLED1_EXPORT Derived : public Base { public: Derived(); void setC(double d); double getC(); private: char arrCh[100]; //Add later to update the DLL double c; };
Below is the client code,
base.h
、derived.h
included aren't same as in the DLL, one is annotated and one not. Implementation and declaration are separate in the DLL.I tried to access the variable directly and access the variable by funcation(such as annotated at the beginning ofmain.cpp
).//main.cpp #include "dpbase.h" #include "dpbase2.h" #include <QDebug> #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); Base base; qDebug() << base.getA(); qDebug() << base.getB(); Derived base2; base2.setC(50); qDebug() << base2.getC(); return a.exec(); }
Among them, class
Base
,Derived
is exported from dll.No matter how I add member variable to whetherBase
orDerived
anywhere,there are no crash and not breaking binary compatibility.I am using qt.There is a same question here, but no help for me.
Furthermore, I delete all member var of class in the DLL, I still use nonexistent variable in the client by linking the DLL,assign value, get it...It seems that there is enough space reserved in the dynamic library to be redefined by the client, even if no member variable is defined.So strange!
My question is, why changing the layout of members of class in the DLL, will not break binary compatibility?And deleting all member var of class in the DLL but why the caller can still use members in the .h file?
@Crawl-W said in Add member variable to class in the shared library, will not break binary compatibility?:
My question is, why changing the layout of members of class in the DLL, will not break binary compatibility?
Changing the layout of members DOES break binary compatibility! Your example just doesn't show the effects of breaking compatibility.
Binary compatibility matters when you want to replace the DLL without recompiling the appplication.
Here's a simpler example:
// Header for DLL class UNTITLED1_EXPORT SimpleClass { public: void setC(double d) { c = d; } double getC() { return c; } char arrCh[100]; //Add later to update the DLL double c; };
int main(int argc, char *argv[]) { ... SimpleClass sc; sc.setC(50); qDebug() << sc.c; // This line probably WON'T print "50" after you replace the DLL qDebug() << sc.getC(); // This line WILL still print "50" after you replace the DLL ... }
To see the effects, you must:
- Build your original DLL
- Build your original application using the original headers and link it to the original DLL.
- Update the DLL code and build your new DLL
- Put the DLL where your application expects to load it
- DO NOT REBUILD YOUR APPLICATION. Just run the original application.
-
@Crawl-W said in Add member variable to class in the shared library, will not break binary compatibility?:
My question is, why changing the layout of members of class in the DLL, will not break binary compatibility?
Changing the layout of members DOES break binary compatibility! Your example just doesn't show the effects of breaking compatibility.
Binary compatibility matters when you want to replace the DLL without recompiling the appplication.
Here's a simpler example:
// Header for DLL class UNTITLED1_EXPORT SimpleClass { public: void setC(double d) { c = d; } double getC() { return c; } char arrCh[100]; //Add later to update the DLL double c; };
int main(int argc, char *argv[]) { ... SimpleClass sc; sc.setC(50); qDebug() << sc.c; // This line probably WON'T print "50" after you replace the DLL qDebug() << sc.getC(); // This line WILL still print "50" after you replace the DLL ... }
To see the effects, you must:
- Build your original DLL
- Build your original application using the original headers and link it to the original DLL.
- Update the DLL code and build your new DLL
- Put the DLL where your application expects to load it
- DO NOT REBUILD YOUR APPLICATION. Just run the original application.
wrote on 12 Aug 2020, 02:27 last edited by@JKSH Thanks,I got it.I have done a similar test before and I don’t know why the error is not triggered.No matter what, your answer clearly proves that will break binary compatibility.