I get different results on UNIX and WIN when using static elements with static binding of the shared library to the executable. Please explain why?

Please consider the following code:

// 1. Single header file. Imagine that it is some static library.
// Counter.h
#pragma once

struct Counter
{
    Counter()
    { 
        ++getCount();
    }

    static int& getCount()
    {
        static int counter = 0;
        return counter;
    }
};

// 2. Shared library (!) : 
// main_DLL.cpp
#include <iostream>
#include "counter.h"

extern "C"
{
   __declspec(dllexport) // for WIN
   void main_DLL()  
   {
       Counter c;
       std::cout << "main_DLL : ptr = " << &Counter::getCount()<< " value = " << Counter::getCount() << std::endl;
   }
}

// 3. Executable. Shared library statically (!) linked to the executable file.
// main.cpp

#include "counter.h"
#include <iostream>

extern "C"
{
    __declspec(dllimport) // for WIN
    void main_DLL();
}

int main()
{
    main_DLL();
    Counter c;
    std::cout << "main_EXE : ptr = " << &Counter::getCount() << " value = " << Counter::getCount() << std::endl;
}

Results:

Results for WIN (Win8.1 gcc 5.1.0):
main_DLL : ptr = 0x68783030 value = 1
main_EXE : ptr = 0x403080 value = 1
// conclusion: two different counters

Results for UNIX (Red Hat <I don’t remember version exactly> gcc 4.8.3):
main_DLL : ptr = 0x75693214 value = 1
main_EXE : ptr = 0x75693214 value = 2
// conclusion: the same counter addressed

Building:

Building for WIN:
g++ -c -Wall -Werror -o main_DLL.o main_DLL.cpp
g++ -shared -Wl,--out-implib=libsharedLib.a -o libsharedLib.so main_DLL.o
g++ -Wall –Werror -o simpleExample main.cpp -L./ -lsharedLib

Building for UNIX:
g++ -c -Wall -Werror -fPIC -o main_DLL.o main_DLL.cpp
g++ -shared -fPIC -o libsharedLib.so main_DLL.o
g++ -Wall –Werror -fPIC -o simpleExample main.cpp -L./ -lsharedLib

So you see that I added -fPIC on UNIX, and there is no need to create an import library for UNIX, because all export characters are included in the shared library. On Windows, I use __declspec for this.

For me, results on Windows are pretty much expected. Since the shared library and the executable are built separately, they should be aware of the static variable in Counter :: getCount. They should just allocate memory for this, so they have different static counters.

, nm, objdump. , . , .

ldd, , .

Unix , . (, -fPIC) Im - ?

+4
2

Windows, DLL , dllexport, , , .

linux/unix shared lib , , lib, .

.

+4

EDIT: . .


, . , , .

" Dependency Walker.

( -), Windows ( EXE, DLL) , /, DLL. , , , , MSVC. ( , .)

( ). .

Linux Windows

SHR , . .

Linux . , Windows , .

GCC Windows. . GCC Wiki.

, Linux Windows. , , , , . , ( Windows) . __declspec .

?

Windows. / __declspec. . (, , - #define , GCC Wiki. )

, . . , :

class __declspec(dllexport) Counter { /* ... */ };

/ , /.

!

, ? , GCC MSVC -.

( Dependency Walker), . .

MSVC 2013 Express Edition 5. GCC MinGW distro nuwen.net, 13.0.

MSVC . (, ). . , static, (!).

GCC, , . . , .

/

, GCC . static .

, , GCC . GCC , . , ( ) . GCC.

MSVC . , , .

, , MSVC static, ( ), static. (N3337, ++ 11) 7.1.2 ([dcl.fct.spec]) 4 , :

(...) . (...)

, . MSVC ( : ), .

. , getCount / .

, -, , GCC MSVC. , , MSVC , , GCC.

. , GCC MSVC.

static. ( , static class) . .

, ( ), / static. , .

MSVC-

MSVC .

/, ( ) .

, GCC MSVC Windows . , .

() Linux Windows, (GCC) .

, : GCC Linux, GCC Windows MSVC Windows. comment.

, /. . Windows ( ) ( , ).

, . . , ( ). ( ), , . , . , .

GCC Wiki. , ( ) Linux, ( ) . , Windows, .

+1

Source: https://habr.com/ru/post/1598539/


All Articles