在 DLL 构建过程中包含特定文件时,LoadLibrary 失败

4
我在C++应用程序的一个DLL中遇到了奇怪的行为。它能正常工作和加载,直到我在DLL的主文件中使用#include包含单个文件。然后我得到了这个错误信息:

从D:/Targets/bin/MatrixWorkset.dll加载组件 不能加载"D:/Targets/bin/MatrixWorkset.dll":无法加载库MatrixWorkset:内存地址访问无效。

现在我已经在代码和Google中搜索了很久,但还是弄不清楚发生了什么。直到现在,一切都在一个单独的DLL中,我决定将其拆分成两个较小的DLL。导致问题的文件是另一个第二个库的一部分(可以正常加载)。

如果有任何想法,真的会非常感激。 谢谢, Jaco


展示一些代码,一个# include可以实现任何功能。 - Ismael
好的,在更多的调试之后,发现(带有MatrixVariable类的)文件甚至不需要被包含在任何其他文件中。我只需要将它添加到DLL的make文件中,这样就会破坏DLL。MatrixVariable继承自第二个DLL中的一个类,就是这样。当只使用一个DLL时,它可以正常工作。 - Jaco
6个回答

6
可能的原因是存在一个类类型的全局变量。构造函数在DllMain()中运行,而DllMain()又在LoadLibrary()返回之前运行。在DllMain()返回之前,有很多限制条件需要遵守。

1
在DllMain()返回之前,有很多限制,比如什么?请提供链接... - Gili

2
有可能头文件中包含 #pragma comment(lib,"somelibrary.lib") 语句吗?如果是的话,它会自动尝试导入一个库。
要解决这个问题,我建议先使用 depends(http://www.dependencywalker.com/)查看二进制文件,以查看是否有任何你不希望出现的 DLL 依赖项。如果确实找到了某些东西,并且你正在使用 Visual Studio,则应该在链接器上打开 "显示进度",也就是 /VERBOSE。
由于你收到了“无效访问内存位置”的错误,所以可能是 DLLMAIN 或一些静态初始化器崩溃了。你能简化 MatrixWorkset.dll 吗(假设是你写的)?

我很确定包含的文件中没有 #pragma,因为我自己写了它,并且在另一个也使用它的 DLL 中包含时可以正常工作。在依赖项查看器中一切看起来都很好。不工作的 DLL 中有一个依赖的 DLL 的重复副本,而工作的 DLL 中并非如此。 - Jaco
另外,我已经简化了MatrixWorkset.dll,直到在不包括头文件时它可以正常工作。我已将这个工作副本与不工作的副本进行了比较,唯一的区别是重复的DLL。 - Jaco

0
最近我从一个命令行EXE中加载DLL失败时,通过GetLastError()函数得到了这个错误。以前它是可以工作的,但是我现在添加了一些MFC代码到DLL中,现在就不确定了。

0
我曾经遇到过这个问题。一个之前一直正常工作的dll突然停止工作了。我在初始化静态对象的CRT代码中遇到了访问冲突。重新构建并不能解决问题。但是当我手动注释掉所有的静态对象时,链接器报告文件损坏。重新链接后:问题解决了。现在我可以LoadLibrary了。然后,我逐个添加静态对象。每次添加后,我都重新编译并测试LoadLibrary。每次都正常工作。最终,我的所有静态对象都回来了,一切正常。
如果我要猜测,可能是链接器使用的某个中间文件被损坏了(我经常看到link.exe导致ilk文件损坏)。如果可以的话,也许可以清除所有文件并进行干净的构建?但我猜你已经解决了问题,因为这已经是6个月前的事情了...

0

你描述的错误听起来像是运行时错误。这个错误是Windows自动显示的还是你的程序发出的?

我建议给你的应用程序附加一个调试器,并追踪错误的来源。是Windows无法加载依赖项吗?还是你的库在加载时出现了问题?

如果你想排除或确认包含的头文件是否有问题,可以尝试分别使用和不使用这个#include预编译你的主源文件,然后对比两次的结果。


0

我还是没搞定。让我回答一些问题:

1)Windows没有加载依赖项失败,因为Dependency Walker显示一切正常。 2)当它尝试加载MatrixWorkset.dll时,我附加了一个调试器,基本上会打印以下内容:

            10:04:19.234
stdout:&"warning: Loading components from D:/ScinericSoftware/VisualWorkspace/trunk/Targets/bin/MatrixWorkset.dll\n"
            10:04:19.234
stdout:&"\n"
status:Stopped: "signal-received"
status:Stopped.
            10:04:19.890
stdout:30*stopped,reason="signal-received",signal-name="SIGSEGV",signal-meaning="Segmentation fault",thread-id="1",frame={addr="0x7c919994",func="towlower",args=[],from="C:\\WINDOWS\\system32\\ntdll.dll"}
input:31info shared
input:32-stack-list-arguments 2 0 0
input:33-stack-list-locals 2
input:34-stack-list-frames
input:35-thread-list-ids
input:36-data-list-register-values x
            10:04:19.890

3) MSalters:我不确定你所说的“全局类类型”是什么意思。出现问题的文件已被包含在不同的DLL中,在其中它工作正常且DLL已成功加载。

这是MatrixVariable.h文件的顶部内容:

#include "QtSF/Variable.h" //位于依赖的DLL中(此文件始终存在的DLL)。
#include "Matrix.h" //文件位于此DLL中
#include "QList" //这些都是来自Qt框架的文件
#include "QModelIndex"
#include "QItemSelection"
#include "QObject"

using namespace Zenautics;
using namespace std;
class MatrixVariable : public Variable { Q_OBJECT Q_PROPERTY(int RowCount READ rowCount WRITE setRowCount) Q_PROPERTY(int ColumnCount READ columnCount WRITE setColumnCount) Q_PROPERTY(int UndoPoints READ undoPoints WRITE setUndoPoints) public: //! 默认构造函数。 MatrixVariable(const QString& name, int rows, int cols, double fill_real = 0, double fill_complex = 0, bool isReal = true);

等等等等。

一个可能的解决方案是将MatrixVariable文件放回原来的DLL中,但这违背了将DLL拆分成更小部分的整体思路,这并不是一个真正的选择。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接