90 lines
3.1 KiB
Plaintext
90 lines
3.1 KiB
Plaintext
[/
|
|
Copyright 2016-2019 Antony Polukhin
|
|
Distributed under the Boost Software License, Version 1.0.
|
|
(See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
/]
|
|
|
|
[section Missuses]
|
|
|
|
[warning Typical errors and missuses are located in this section. Please read carefully, this will save a lot of debugging time!]
|
|
|
|
* [*Issue:] Program crashes on `delete` or `free()`.
|
|
* [*Fix:] Your plugin and program must use the same Standard C++ and C libraries, both must be linked dynamically. For Visual Studio use [@https://msdn.microsoft.com/library/2kzt1wy3%28v=vs.110%29.aspx /MD or /MDd compiler switches].
|
|
|
|
[pre
|
|
]
|
|
|
|
|
|
* [*Issue:] Program crashes in `catch(...)` block.
|
|
* [*Example:]
|
|
```
|
|
try {
|
|
auto f = dll::import<int()>(path_to_pugin, "function");
|
|
f();
|
|
// `f` goes out of scope
|
|
} catch (const std::exception& e) {
|
|
std::cerr << e.what();
|
|
}
|
|
```
|
|
* [*Fix:] Exception was generated inside the plugin, so it refers to the exception code in plugin. When `f` goes out of scope, the plugin gets unloaded and the reference to the exception code is broken. Any attempt to use the exception variable may use the dangling reference, leading to a segmentation fault. Fix your code:
|
|
```
|
|
auto f = dll::import<int()>(path_to_pugin, "function");
|
|
try {
|
|
f();
|
|
// `f` goes out of scope
|
|
} catch (const std::exception& e) {
|
|
std::cerr << e.what();
|
|
}
|
|
```
|
|
|
|
[pre
|
|
]
|
|
|
|
* [*Issue:] Thread local storage seems to be corrupted.
|
|
* [*Fix:] Some platforms have no out-of-the-box support for plugins that use TLS, for example [@https://support.microsoft.com/en-us/kb/118816 Windows]. Use platform specific workarounds or just do not use TLS in plugins.
|
|
|
|
[pre
|
|
]
|
|
|
|
* [*Issue:] Attempt to call a loaded function crashes or function returns incorrect result.
|
|
* [*Fix:] Boost.DLL does not guarantee ABI stability. If you compile plugin and program with different compilers or different compiler switches the function ABI may change and you'll end up with incorrect code.
|
|
|
|
[pre
|
|
]
|
|
|
|
* [*Issue:] Program crashes after plugin unload.
|
|
* [*Example:]
|
|
```
|
|
void foo() {
|
|
shared_ptr<int> p;
|
|
try {
|
|
auto f = dll::import<shared_ptr<int>()>(path_to_pugin, "function");
|
|
p = f();
|
|
// `f` goes out of scope
|
|
} catch (const std::exception& e) {
|
|
std::cerr << e.what();
|
|
}
|
|
std::cout << *p;
|
|
// crashes here
|
|
}
|
|
|
|
```
|
|
* [*Fix:] In that particular example the problem is within `shared_ptr<int>`. It keeps a type erased deleter, code for that deleter is located in plugin. On destruction of `p`, `shared_ptr<int>` attempts to call that deleter, however the plugin was already unloaded and the code for deleter is not available any more.
|
|
|
|
* [*Rule of thumb:]: if your plugin method returns any C++ class variable, then make sure that the plugin is loaded until that variable and any of its copies are in scope.
|
|
|
|
* [*Typical classes that cause such errors are:]
|
|
* `any`
|
|
* `function`
|
|
* `shared_ptr`
|
|
* any container with polymorphic allocator
|
|
* `std::type_index`
|
|
* `std::type_info`
|
|
* `std::exception_ptr`
|
|
* `std::unique_ptr<Base>` holding a `Derived` type from plugin
|
|
* exception classes thrown from plugin
|
|
|
|
[pre
|
|
]
|
|
[endsect]
|