[contract] "Duplicated globals" problem

Hi Lorenzo, I think that installing broken contract handlers will not work correctly when a program is linking with DLLs on Windows. I do not know how dynamic linking works on Linux. Here is a sketch of a sample program that fails to work as expected. The program consists of two projects: one builds a DLL, the other builds an executable that links with the DLL: DLL: ==================================== # include <contract.hpp> # include "testdll.h" CONTRACT_FUNCTION ( int (give1) () postcondition(auto result = return, result == 1) ) { return 2; // obviously wrong } DLL_MODE void test_contracts() { int i = give1(); } ==================================== EXE: ==================================== # include <contract.hpp> # include "../testdll/testdll.h" void PostconditionHandler( contract::from const& context ) { std::cerr << "ERROR!!!" << std::endl; } int main() { contract::set_postcondition_broken(&PostconditionHandler); test_contracts(); } ==================================== I expect that the program would use the broken postcondition handler I installed, but it still uses the default one. The cause is that Contract is using some global object to store the installed handler, but when a program is linked with a DLL both the program and the DLL store their own copy of the global. The global is duplicated. THe one in the EXE registers my callback, but the global in the DLL still keeps the default handler. The only way to solve this issue is to -- at least in the cases when users' programs link with DLLs -- ship Contract with a small DLL that stores the unique copy of the globals. This is how Boost.Log handles this problem. Quoting the documentation ( http://boost-log.sourceforge.net/libs/log/doc/html/log/installation.html): *"If your application consists of more than one module (e.g. an exe and one or several dll's) that use Boost.Log, the library must be built as a shared object. If you have a single executable, you may build the library as a static library." * Regards, &rzej* *

Hi Andrzej, On Sat, Aug 25, 2012 at 1:52 PM, Andrzej Krzemienski <akrzemi1@gmail.com> wrote:
Hi Lorenzo, I think that installing broken contract handlers will not work correctly when a program is linking with DLLs on Windows. I do not know how dynamic linking works on Linux. Here is a sketch of a sample program that fails to
Yes, this is a bug and I just entered a ticket for it https://sourceforge.net/apps/trac/contractpp/ticket/60. I'll fix it as you suggest below. This also applies at the global variable used by the library to implement the Contract Programming requirement to "disable assertions within assertions" so to prevent infinite recursion. Thanks, --Lorenzo
work as expected. The program consists of two projects: one builds a DLL, the other builds an executable that links with the DLL:
DLL: ==================================== # include <contract.hpp> # include "testdll.h"
CONTRACT_FUNCTION ( int (give1) () postcondition(auto result = return, result == 1) ) { return 2; // obviously wrong }
DLL_MODE void test_contracts() { int i = give1(); } ====================================
EXE: ==================================== # include <contract.hpp> # include "../testdll/testdll.h"
void PostconditionHandler( contract::from const& context ) { std::cerr << "ERROR!!!" << std::endl; }
int main() { contract::set_postcondition_broken(&PostconditionHandler); test_contracts(); } ====================================
I expect that the program would use the broken postcondition handler I installed, but it still uses the default one. The cause is that Contract is using some global object to store the installed handler, but when a program is linked with a DLL both the program and the DLL store their own copy of the global. The global is duplicated. THe one in the EXE registers my callback, but the global in the DLL still keeps the default handler.
The only way to solve this issue is to -- at least in the cases when users' programs link with DLLs -- ship Contract with a small DLL that stores the unique copy of the globals. This is how Boost.Log handles this problem. Quoting the documentation ( http://boost-log.sourceforge.net/libs/log/doc/html/log/installation.html):
*"If your application consists of more than one module (e.g. an exe and one or several dll's) that use Boost.Log, the library must be built as a shared object. If you have a single executable, you may build the library as a static library."
* Regards, &rzej* *
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
participants (2)
-
Andrzej Krzemienski
-
Lorenzo Caminiti