为啥在我使用导入的 .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 以及 #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 的“资源文件”文件夹中链接了 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.hGENERIC.cpp 中的所有代码放入一个文件中,并且#included 将该文件全部作为内联代码,那么它可能会起作用。所以我试了一下,它编译得很好,运行良好。

问题(

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

编辑(为什么!?)

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

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

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

【问题讨论】:

使用调试器并查看堆栈跟踪以找到最接近违规代码的调用站点。 @CaptainObvlious 但是代码显然很好,因为当我尝试内联 #includeing 时,我使用了所有相同的代码,它工作得很好。但我会调查一下。 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 未暂停

为啥 Aptana 3 (OS X) 在导入的项目中找不到 django 设置模块?

导入了Gson.jar为啥会用不了?

win下opencv为啥在spyder上运行不了了