Pergunta

I'm building a plugin system with Delphi (some of you have been helping me with this task).

To search for the DLL files, I'm using a TSearchRec, which search's in the exe path for dll files, and then I'm using LoadLibrary to access them. Then, if a certain function is exposed (using GetProcAddress), I load it as a plugin. If not, FreeLibrary is executed, and moves on for the next file.

While testing, I noticed that when the TSearchRec found the "borlndmm.dll", which happened to be in that path, it loads, and searches for my plugin function, which of course is not found, but when if executes FreeLibrary, I get an Access Violation.

Other no-plugin dll's in the same path, like libmariadb.dll, are freed securely without errors.

Of course this is easily fixed, by having my plugin dll's in its own path, without any other dll files, which will be better even for performance reasons, as it doesn't have to load any library that it's not supposed to.

But I would like to understand why it happens. Any ideas?

Thank you Nuno Picado

Foi útil?

Solução 2

That DLL implements a shared memory manager. It is designed to be used with load time linking only. It is loaded by the loader, and never unloaded until the process ends. Once it is loaded, it assumes responsibility for all future heap allocations and deallocations with the process. So it changes the behaviour of the host process. It cannot be loaded dynamically.

The moral of the story is not to load random DLLs into your process. Only load DLLs that either you or your program's users specifically ask to be loaded.

Outras dicas

The reason why you run into problems with some DLLS is because LoadLibrary executes code in the DLL it loads - specifically, the DLL's initialization code. In Delphi projects, this includes the unit initialization sections. In the case of borlandmm.dll, the dll initialization code inserts itself into your host exe process's runtime library, replacing your default memory manager with the memory manager in the DLL. This is not intended to be a reversible action - it can't remove itself in the DLL shutdown code (in part because DLL shutdown code is not guaranteed to execute in all circumstances).

So, be careful using LoadLibrary because you are basically executing arbitrary code before you even know what the DLL is. If you really must take a peek into a large number of arbitrary DLLs of unknown origin, a safer way would be to load the DLL as a resource image instead of as an executable image. This loads the file into memory but does not execute the DLL initialization code. See LoadLibraryEx() and the LOAD_LIBRARY_AS_IMAGE_RESOURCE flag.

As you mentioned in an earlier comment, there are a number of things you can do to reduce the number of DLLs you need to load to exactly the DLLs that the user/administrator wants your application to load, instead of loading everything you can find.

  1. Require the DLL file name have a custom extension or file name pattern. (Plugin*.mod for example)
  2. Only load DLLs from a special subdirectory. This works well with directory level access control, since on most systems bin directories are not writable by ordinary users. Someone would have to have admin rights to put a DLL into the special subdirectory.
  3. Only load DLL files that are named in a user-defined config file.
  4. Any combination of the above
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top