为什么在我 运行 我的项目使用导入的 .lib 时调用 "user breakpoint",而不是在代码内联时调用?

Why is a "user breakpoint" called when I run my project with imported .lib, not when code is inline?

情况

我正在编写一个用于 GPIB 通信的包装器库,用于根据客户规范设置特定仪器以自动化他们的某些过程。我必须在 Windows NT 机器上使用 VC++ 6.0 运行 中的 C++ 和旧的 '98 编译器,以保持与他们经常使用的其他一些设备的兼容性。

我正在尝试制作一个 class 将一些 GPIB 命令组合成更容易记住的功能,同时还保持与仪器直接通信的能力。为此,我将项目的不同部分编译成不同的库和 dll,每个 dll 都是它们可能想要与之通信的不同设备。我还制作了一个通用的 dll 基础 class,所有特定的工具 classes 都从中继承,希望使整个设置尽可能模块化。

问题

所以,综上所述,我在尝试测试不同的 dlls/modules 时遇到了问题。我创建了一个项目来测试通用基础 class,将 .lib 文件添加到项目中,该文件链接到 .dll,并且还 #included 该 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 的 "Resource Files" 文件夹中链接了 GENERIC.lib,并且我可以从路径变量访问 GENERIC.dll

继续,GENERIC.h 看起来像这样(select 部分):

#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!我明白了:"User breakpoint called from code at 0x77f7645c"。所以,然后我想,如果我将 GENERIC.hGENERIC.cpp 中的所有代码放入一个文件中,然后 #included 将该文件全部作为内联代码,也许它会起作用。所以我试了一下,它编译得很好,运行 很好。

问题(<-啊哈!...但是...)

我做错了什么!?我制作 .dll 的方式有问题吗?还是.lib?还是完全不同?

编辑(为什么!?)

所以,经过一番调试,我发现它与传递字符串文字有关。所以我只是将其修改为:

std::string command = "*IDN?";
hp.write(command);

而且效果很好。我的后续问题是为什么?传递字符串文字与将其分配给变量然后传入之间有什么区别?

使用 std::string 等复杂类型作为 DLL 边界的参数是很棘手的。您必须确保 exe 和 DLL 使用完全相同的库代码实例。这要求您构建它们以使用运行时库的相同版本的 DLL 版本。