为啥在我使用导入的 .lib 运行项目时调用“用户断点”,而不是在代码内联时调用?
Posted
技术标签:
【中文标题】为啥在我使用导入的 .lib 运行项目时调用“用户断点”,而不是在代码内联时调用?【英文标题】:Why is a "user breakpoint" called when I run my project with imported .lib, not when code is inline?为什么在我使用导入的 .lib 运行项目时调用“用户断点”,而不是在代码内联时调用? 【发布时间】:2015-06-12 22:36:59 【问题描述】:情况
我正在为 GPIB 通信编写一个包装库,用于根据客户规范设置特定仪器,以自动化他们的一些流程。我必须在 Windows NT 机器上运行的 VC++ 6.0 中使用 C++ 和旧的 '98 编译器,以保持与他们经常使用的其他一些设备的兼容性。
我正在尝试创建一个类,将一些 GPIB 命令组合成更易于记忆的函数,同时保持与仪器直接通信的能力。为此,我将项目的不同部分编译成不同的库和 dll,每个 dll 都是他们可能想要与之通信的不同设备。我还创建了一个通用 dll 基类,所有特定的仪器类都从该基类继承,希望使整个设置尽可能模块化。
问题
所以,尽管如此,当我尝试测试不同的 dll/模块时,我遇到了一个问题。我创建了一个项目来测试通用基类,将 .lib 文件添加到项目中,该文件链接到 .dll 以及 #include
d 该 dll 的头文件。 testGeneric.cpp
看起来像这样:
#include "GENERIC.h"
void main(void)
GPIBInstrument hp(2); //connects to device at primary address #2
hp.write("*IDN?");
超级简单。需要明确的是,我还在 VC++ 6.0 的“资源文件”文件夹中链接了 GENERIC.lib
,并且可以从路径变量访问 GENERIC.dll
。
继续前进,GENERIC.h
看起来像这样(选择部分):
#ifndef GENERIC_H
#define GENERIC_H
#include <string>
#include <windows.h>
#include "decl-32.h"
#ifdef GENERIC_EXPORT
#define GENERIC_API __declspec(dllexport)
#else
#define GENERIC_API __declspec(dllimport)
#endif
...(Inline exception classes)...
class GENERIC_API GPIBInstrument
...
public:
void write(std::string command);
...
;
#endif
只展示相关的方法。然后GENERIC.cpp:
#define GENERIC_EXPORT
#include "GENERIC.h"
...
void GPIBInstrument::write(std::string command)
ibwrt (handle, &command[0u], command.length());
std::cout << command << std::endl;
if (ibsta & TIMO)
timeoutError();
if (ibsta & ERR)
error("Unable to write command to instrument: " + command);
所以,看起来不错吧?没有问题。编译良好。我尝试运行它,然后 BLAM!我得到这个:“从 0x77f7645c 的代码调用用户断点”。所以,然后我想,如果我将GENERIC.h
和GENERIC.cpp
中的所有代码放入一个文件中,并且#include
d 将该文件全部作为内联代码,那么它可能会起作用。所以我试了一下,它编译得很好,运行良好。
问题(
我做错了什么!?与我制作.dll 的方式有关吗?还是.lib?还是完全不同的东西?
编辑(为什么!?)
所以,经过一番调试,我发现它与传递字符串文字有关。所以我只是将其修改为:
std::string command = "*IDN?";
hp.write(command);
而且效果很好。我的后续问题,是为什么?传递字符串文字与将其分配给变量然后将其传入之间有什么区别?
【问题讨论】:
使用调试器并查看堆栈跟踪以找到最接近违规代码的调用站点。 @CaptainObvlious 但是代码显然很好,因为当我尝试内联#include
ing 时,我使用了所有相同的代码,它工作得很好。但我会调查一下。 VC++ 6.0 已经有调试器了吗?
VC++ 6.0 已经有调试器了吗?是的
VC++ 6.0?还不如使用 Turbo C++。
@CaptainObvlious 所以,我发现了“Build->Start Debug”菜单项。酷。
【参考方案1】:
在 DLL 边界处使用复杂类型(例如 std::string)作为参数是很棘手的。您必须确保 exe 和 DLL 使用完全相同的库代码实例。这要求您构建它们以使用相同版本的运行时库的 DLL 版本。
【讨论】:
它们几乎同时在同一个工作区中编译。但我知道这可能是问题所在...... 这使我走上了解决此问题的正确轨道。谢谢。以上是关于为啥在我使用导入的 .lib 运行项目时调用“用户断点”,而不是在代码内联时调用?的主要内容,如果未能解决你的问题,请参考以下文章
为啥我的WEB-INF目录下没有classes目录,导入struts也不在lib目录下,但是可以正常运行!
为啥在我导入模块时 Python 会运行我的模块,如何停止它?
显示 DialogFragment 时调用 Fragment 未暂停