【问题标题】:Crash with new/delete, but not with malloc/free in C++ code在 C++ 代码中使用 new/delete 会崩溃,但不会使用 malloc/free
【发布时间】:2010-06-18 16:44:14
【问题描述】:

我的开发环境是[Windows 7;视觉工作室 2010; x86]。

我有一个很久以前为服务器 2003 构建的 dll。当我在我的项目中使用它并按照新/删除顺序使用类时,应用程序在删除调用期间崩溃。即使在 new 和 delete 之间没有任何其他调用,我也验证了相同的结果。当我用 malloc/free 替换 new/delete 时,没有崩溃。如果我只是声明一个没有 new 的类的实例,则退出范围时不会发生崩溃。

知道可能出了什么问题吗?这是我们公司的内部库,所以我无法命名它和其他类似的东西。

其他信息: 要首先使用这个库,我必须关闭 VS 功能“将 wchar_t 视为内置类型”。

代码很简单

{
   CLogger * myLog = new CLogger(); 
   delete myLog; // Crash happens here 
} 

{ // No crash here 
  CLogger MyLog; 
} 

{ 
  CLogger * myLog = (CLogger *) malloc (sizeof(CLogger)); 
  free (myLog); // This does not crash. 
} 

这是专有库,我不能发布构造函数和析构函数。

【问题讨论】:

  • 请张贴代码。有一百万种可能出错的地方,如果不查看代码,任何一种都无法识别。
  • 请向我们展示您使用 new 和 delete 的实际代码行。类的构造函数和析构函数也会有所帮助。
  • 代码很简单 { CLogger * myLog = new CLogger();删除我的日志; // 这里发生崩溃 } { // 这里没有崩溃 CLogger MyLog; } { CLogger * myLog = (CLogger *) malloc (sizeof(CLogger));免费(我的日志); // 这不会崩溃。这是专有库,我不能发布构造函数和析构函数。
  • 您忘记了第 42 行的毛巾操作员。
  • 第三个区块很讨厌。 mallocfree 只是记忆函数,例如 operator newoperator delete;他们除了获取原始内存之外什么都不做。 “正确”的方式是:void* memory = malloc(sizeof(CLogger)); CLogger* myLog = new (memory) CLogger(); /* delete*/ myLog->~CLogger(); free(memory);

标签: c++ visual-c++ visual-studio-2010 crash new-operator


【解决方案1】:

delete 不仅仅是释放内存:它还调用了之前的析构函数。这意味着该类的析构函数中一定有什么不好的地方。

如果在析构函数中发生未捕获的异常,则整个进程退出 (*)。 正如下面评论的(感谢良好的反馈),这被过度简化了,这里是一个很好的链接,了解更多细节: throwing exceptions out of a destructor

我建议你放一个

try {} catch (std::exception& e){} catch(...) {}

在析构函数内部并注销正在发生的事情,或者最好让它通过调试器,并选择在引发异常的地方停止。

那么应该很容易识别出不同之处。只是我的猜测,可能是一些注册表访问或文件访问权限,从 server 2003 到 windows 7 引入了一些更改。

【讨论】:

  • 这是对从析构函数抛出异常时发生的情况的过度简化。绝对值得一提的是调用 terminate() 所需的确切条件
  • 未捕获的异常只有在堆栈由于另一个异常而展开时发生才会终止进程。
【解决方案2】:

我运用我的心理调试技巧建议您使用delete,而您应该使用delete[]

推理:如果您能够简单地将new 替换为malloc,那么您可能分配了一个原始类型数组而不是一个对象,并且假设您天真地使用delete 代替free对象分配和数组分配在 C++ 中是相同的。 (他们不是。)

【讨论】:

  • 根据我的经验,这可能会造成泄漏,因为只有第一个数组对象的构造函数被调用,但没有崩溃。在这种情况下,我认为这不是问题,而是一个很好的建议。
  • Zhinkaas 必须修改涉及wchar_t 的设置这一事实也为您的观点增加了潜在证据。
  • 我认为这更多是因为 wchar_t 以另一种方式装饰,如果你将它用作内置并且可能使用 c++ 链接到另一个 dll 并将 va 将签名变成短裤链接不正确编译,否则很多或未解析的符号。 @Zhinkaas 纠正我,我错了。
  • msdn.microsoft.com/en-us/library/799kze2z(VS.80).aspx 需要 wchar_t 相关的 hack(LNK2019 错误)。正如您可以看到上面发布的表单代码,诊断出缺少 [] 的情况并非如此。
猜你喜欢
  • 1970-01-01
  • 2015-05-28
  • 2014-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多