你能解释一下这个 C++删除问题?

发布于 2024-08-23 15:09:53 字数 589 浏览 7 评论 0原文

我有以下代码:

std::string F()
{
  WideString ws = GetMyWideString();

  std::string ret;
  StringUtils::ConvertWideStringToUTF8(ws, ret);
  return ret;
}

WideString是第三方类,StringUtils也是。他们对我来说是一个黑匣子。第二个参数通过引用传递。

当我单步执行调试器时,return ret 行会抛出一个令人讨厌的弹出窗口 (Visual C++),指出堆可能已损坏。仔细检查返回的字符串副本是可以的,但是 ret 的删除失败。 ret 在返回之前包含正确的值。

转换函数可能会做什么导致这种情况?有什么想法要解决吗?

更新:

  • 项目本身是一个 dll
  • StringUtils 是一个 lib
  • 项目是针对多线程 CRT 编译的(不是调试,不是 dll)
  • 程序在 Visual Studio 之外运行时似乎运行良好

I have the following code:

std::string F()
{
  WideString ws = GetMyWideString();

  std::string ret;
  StringUtils::ConvertWideStringToUTF8(ws, ret);
  return ret;
}

WideString is a third-party class, so are StringUtils. They are a blackbox to me. Second parameter is passed by reference.

When I step through the debugger the line return ret throws a nasty popup (Visual C++) saying that heap may be corrupted. Upon closer examination copy of the string that gets returned is OK, but the deletion of ret fails. ret contains correct value before return.

What could the converting function possibly do to cause this? Any ideas to fix?

Update:

  • Project itself is a dll
  • StringUtils is a lib
  • Project is compiled against Multithreaded CRT (not debug, not dll)
  • Program seems to run fine when run outside of Visual Studio

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

鯉魚旗 2024-08-30 15:09:53
  1. 如果 StringUtils 是单独编译的(例如,使用不同的编译器版本),则对象布局可能会发生冲突。
  2. 如果 StringUtils 在 DLL 中,则必须确保它和主程序都被编译为使用 DLL 中的标准库。否则,每个模块(可执行文件和 DLL)将有自己的堆。当 StringUtils 尝试使用从不同堆分配的字符串中的数据时,就会发生不好的事情。
  1. If StringUtils was compiled separately (e.g., with a different compiler version), you may have a conflict in the object layout.
  2. If StringUtils is in a DLL, you have to ensure that both it and the main program are compiled to use the standard library in a DLL. Otherwise, each module (executable and DLL) will have its own heap. When StringUtils tries to play with data in the string that was allocated from a different heap, bad things happen.
似梦非梦 2024-08-30 15:09:53

StringUtils的设计者设计了一个非常糟糕的API。 API 的公共接口中不应使用任何模板化标准库类型。 std::string 内联被吹出。所以如果编译器 &您使用的库不是完全相同的编译器和库; StringUtils 的实现者使用的库,类型可以而且很可能会有所不同。从根本上来说,StringUtils 的实现者未能将接口与实施

问题的例证。假设您使用的是 MSVC 9.0 SP1,而我使用的是 MSVC 8.0。在我的编译器上, std::string 的实现可能如下所示:

class string
{
// : :  stuff
private:
  int someInt_;
  char* someBuf_;
};

...但在您的编译器上,它可能看起来不同:

class string
{
// : :  stuff
private: 

  void* impl_;
};

如果我编写一个库函数:

void DoSomethingWithAString(std::string& str);

... 并且您调用它,则 sizeof(string您的代码中的 ) 将与我的代码中的 sizeof(string) 不同。类型不相同。

您实际上只有 2 个解决方案来解决您的问题:

1)[首选] 让 StringUtils 的实现者修复他损坏的代码。

2) 替换编译器使用的库以匹配 StringUtil 的实现者使用的库。您可以通过使用与实现者使用的补丁级别相同的编译器来完成此任务,假设他没有替换标准库的实现。

编辑:3)第三种选择是停止使用 StringUtils。老实说,这可能就是我会做的。

The designer of StringUtils designed a very poor API. None of the templated Standard library types should be used in the API's public interface. std::string is blown out inline. So if the compiler & libraries you are using is not the exact same compiler & libraries used by the implementor of StringUtils, the types can and likely will be different. Fundamentally, the implementor of StringUtils failed to separate the interface from the implementation.

An illustration of the problem. Suppose you are using MSVC 9.0 SP1 and I am using MSVC 8.0. On my compiler, the implementation of std::string might look like this:

class string
{
// : :  stuff
private:
  int someInt_;
  char* someBuf_;
};

...but on your compiler it might look different:

class string
{
// : :  stuff
private: 

  void* impl_;
};

If I write a library function:

void DoSomethingWithAString(std::string& str);

... and you call it, the sizeof(string) in your code will be different than the sizeof(string) in my code. The types are NOT the same.

You really only have 2 solutions to your problem:

1) [preferred] Get the implementor of StringUtils to fix his broken code.

2) Replace the library used by your compiler to match the library used by StringUtil's implementor. You might be able to accomplish this by using the same compiler at the same patch level as the implementor used, assuming he didn't replace the implementation of the standard library.

EDIT: 3) A third option would be to stop using StringUtils. Honestly this is probably what I'd do.

打小就很酷 2024-08-30 15:09:53

从您显示的一小段代码来看,我认为 StringUtils::ConvertWideStringToUTF8() 采用 std::string& 作为第二个参数。鉴于此,我不明白你的代码如何导致堆损坏。

但请注意,C++ 库的链接通常仅在所有代码均使用相同的编译器和相同的编译器设置进行编译时才有效。

From what little code you show, I suppose StringUtils::ConvertWideStringToUTF8() takes a std::string& as a second parameter. Given that, I don't see how your code can cause a heap corruption.

Note, however, that linking of C++ libraries in general only works when alls the code was compiled using the same compiler and the same compiler settings.

提笔书几行 2024-08-30 15:09:53

您对 StringUtilsWideString 的使用使得您看起来像是在使用 C++ Builder。您是否尝试混合使用 C++ Builder 模块和 Visual C++ 模块?如果是这样,那么您肯定会看到您所描述的问题。

无法将 Visual C++ std::string 传递给 C++ Builder 函数,因为 C++ Builder 代码将假定该参数使用 C++ Builder 的 std::string 定义。这些类可能具有不同的字段,并且它们共有的字段可能具有不同的顺序。

即使类具有相同的定义,模块仍将使用不同的内存管理器。被调用的函数将使用其内存管理器为新字符串内容分配内存,调用者将使用自己的内存管理器稍后尝试释放字符串的内容。

Your use of StringUtils and WideString makes it look like you're using C++ Builder. Are you trying to mix a C++ Builder module and a Visual C++ module? If so, then you'd definitely see the problems you've described.

You can't pass a Visual C++ std::string to a C++ Builder function because the C++ Builder code will assume that the parameter uses C++ Builder's std::string definition. The classes might have different fields, and the fields they have in common might be in a different order.

Even if the classes have the same definitions, the modules will still use different memory managers. The called function will allocate memory for the new string contents using its memory manager, and the caller will use its own memory manager to attempt to free the string's contents later.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文