Zmienne globalne w 64bit

0

Witam,

  Piszę aplikację w C++, która korzysta z bibliotek dll i mam problem z dostępem do zmiennych globalnych dllki ale tylko przy kompilacji 64 bitowej.

Przykładowy kod aplikacji głównej

 
// dostępne również w bibliotece DLL
typedef struct InfoStruct
{
	int Size;
	char* name;
}LoadStruct;

typedef struct LoadStruct
{
	int (__stdcall *DoAction)( InfoStruct* );
}LoadStruct;

extern "C" int __stdcall DoAction(InfoStruct* info)
{
	printf(L"%d [%s]", info->Size, info->name);
	return 0;
}

LoadStruct LoadData;
HINSTANCE hDll;

int Load(char* DllPath)
{
	hDll = LoadLibrary( DllPath );

	typedef int( __stdcall * LoadPROC )( LoadStruct* );
	LoadPROC proc;

	if( hDll != NULL )
	{
		proc = ( LoadPROC )GetProcAddress( hDll, "Load" );

		if(!proc)
			return 0;

		LoadData.DoAction = &DoAction;

		if(!proc(&LoadData))	// przekazuję strukturę z adresem funkcji DoAction
			return 0;
	}
	
	return 1;
}

Oraz kod biblioteki DLL

LoadStruct* LoadData;
InfoStruct InfoData;

extern "C" int __stdcall Load(LoadStruct* _LoadData)
{
	LoadData = _LoadData;
	return 1;
}

int JakasFunkcja()
{
	InfoData.Size = 5;
	InfoData.name = "nazwa";
	return LoadData->DoAction(&InfoData);
}

Podczas gdy wywołanie funkcji "JakasFunkcja" na 32 bitach nie robi problemu to na 64bitach dostaję Access violation.

Ale już takie kody(DLL) działają bez problemu

// pierwszy
int JakasFunkcja()
{
	InfoStruct InfoData;
	InfoData.Size = 5;
	InfoData.name = "nazwa";
	return LoadData->DoAction(&InfoData);
}

// drugi
InfoStruct* InfoData = NULL;
int JakasFunkcja()
{
	if(!InfoData)
		InfoData = new InfoStruct;
	InfoData->Size = 5;
	InfoData->name = "nazwa";
	return LoadData->DoAction(&InfoData);
}

Wychodzi na to, że aplikacja nie ma dostępu do zmiennej globalnej biblioteki ale według MSDN każda aplikacja główna otrzymuje własną kopię zmiennych globalnych

Variables that are declared as global in a DLL source code file are treated as global variables by the compiler and linker, but each process that loads a given DLL gets its own copy of that DLL's global variables. The scope of static variables is limited to the block in which the static variables are declared. As a result, each process has its own instance of the DLL global and static variables by default.

http://msdn.microsoft.com/en-us/library/windows/desktop/ms682594%28v=vs.85%29.aspx
I teraz jest pytanie, czy DLL nie może przesyłać adresu do zmiennej globalnej zadeklarowanej w sobie? Przypomnę, że dla aplikacji 32bitowej działa poprawnie.

0

Czy bibliotekę DLL również kompilujesz pod 64?

0

Tak, aplikacja oraz dll jest kompilowana pod x64

0
  1. Nie pokazałeś w którym miejscu program się wywala, a siedzę na 32-bitowym systemie więc nie mam jak kodu przetestować.
    Parę rzeczy które mi przyszły do głowy:
typedef struct InfoStruct
{
        int Size;
        char* name;
}LoadStruct;

Próbowałeś odwrócić kolejność pól? Może EXE i DLL z jakiegoś powodu mają inny alignment, a ponieważ int i char* mają różne rozmiary w 64 bitach, struktura może inaczej być rozłożona...
Sprawdź czy sizeof(InfoStruct) jest takie samo w EXE i w DLL-ce.

int Load(char* DllPath)
{
        hDll = LoadLibrary( DllPath );

To raczej nie pomoże, ale jeśli już chcesz ładować dynamicznie, to zrób raczej coś w ten deseń:

HINSTANCE hDll;

int Load(char* DllPath)
{
        static LoadPROC proc;

        if (hDll == NULL)
                hDll = LoadLibrary(...);

        if (proc == NULL)
                proc = GetProcAddress(...);

        if (proc != NULL)
                proc(...);
        ...
}

czyl ładuj wszystko leniwie, a nie za każdym razem.

1 użytkowników online, w tym zalogowanych: 0, gości: 1