C++ 类构造函数可以内联或不内联。但是,我发现了一个奇怪的情况,只有内联类构造函数才能避免 Visual Studio 内存崩溃。示例如下:
dll.h
class _declspec(dllexport) Image
{
public:
Image();
virtual ~Image();
};
class _declspec(dllexport) Testimage:public Image
{
public:
Testimage();
virtual ~Testimage();
};
typedef std::auto_ptr<Testimage> TestimagePtr;
dll.cpp
#include "dll.h"
#include <assert.h>
Image::~Image()
{
std::cout<<"Image is being deleted."<<std::endl;
}
Image::Image()
{
}
Testimage::Testimage()
{
}
Testimage::~Testimage()
{
std::cout<<"Geoimage is being deleted."<<std::endl;
}
dll库编译为动态库,静态链接到C++运行时库(Multi-threaded Debug (/MTd))。运行该库的可执行程序如下:
int main()
{
TestimagePtr my_img(new Testimage());
return 0;
}
可执行程序将调用 dll 库,它还会静态链接运行时库。我遇到的问题是在运行可执行程序时出现以下错误消息:
但是,当dll中的类构造函数被内联时,如下代码所示:
class _declspec(dllexport) Image
{
public:
Image();
virtual ~Image();
};
class _declspec(dllexport) Testimage:public Image
{
public:
Testimage()
{
}
virtual ~Testimage();
};
崩溃将消失。有人可以解释背后的原因吗?谢谢!对了,我用的是VC2010。
编辑: 以下情况也会触发同样的崩溃 .
情况一
int main()
{
//TestimagePtr my_img(new Testimage());
Testimage *p_img;
p_img = new Testimage();
delete p_img;
return 0;
}
最佳答案
it is statically linked to the C++ runtime library (Multi-threaded Debug (/MTd)
在 VS2012 之前的 Visual Studio 版本中,这是一个非常有问题的场景。问题是您的进程中加载了多个版本的 CRT。一个由您的 EXE 使用,另一个由 DLL 使用。这可能会导致许多微妙的问题,而不是像这次崩溃这样微妙的问题。
CRT 具有全局状态,当全局状态由 CRT 的一个拷贝更新并由另一个拷贝读回时,像 errno 和 strtok() 这样的东西无法正常工作。与您的崩溃相关,隐藏的全局状态变量是 CRT 用于从中分配内存的堆。 malloc() 和::operator new 等函数使用该堆。
当对象由 CRT 的一个拷贝分配并由另一个拷贝释放时,就会出错。传递给 free() 或::operator delete 的指针属于错误的堆。接下来会发生什么取决于您的操作系统。 XP 中的静默内存泄漏。在 Vista 及更高版本中,您的程序在启用内存管理器的调试版本的情况下运行。当你有一个调试器附加到你的进程来告诉你指针有问题时,它会触发一个断点。屏幕截图中的对话框就是结果。我不太清楚内联构造函数如何产生影响,但是根本问题是您的代码调用未定义的行为。它具有产生随机结果的诀窍。
有两种方法可以解决这个问题。第一个是简单的,只需使用/MD 编译选项构建 EXE 和 DLL 项目即可。这将选择 CRT 的 DLL 版本。它现在由两个模块共享,您的进程中将只有一个 CRT 拷贝。因此不再有一个模块分配内存和另一个模块释放内存的问题,使用相同的堆。
这可以很好地解决您的问题,但以后仍然会成为问题。 DLL 往往有自己的生命,并且可能有一天会被使用不同版本的 CRT 构建的另一个 EXE 使用。 CRT 现在将不再共享,因为它们将使用不同版本的 DLL,调用您今天看到的完全相同的故障模式。
保证这种情况不会发生的唯一方法是仔细设计您的 DLL 接口(interface)。并确保永远不会出现 DLL 分配客户端代码需要释放的内存的情况。这需要放弃很多 C++ 好东西。例如,您永远不能编写返回 C++ 对象的函数,如 std::string。而且你永远不能允许异常跨越模块边界。您基本上只能使用 C 风格的接口(interface)。请注意 COM 如何通过使用基于接口(interface)的编程技术和类工厂加上引用计数来解决内存管理问题来解决这个问题。
VS2012有针对这个问题的对策,它有一个从默认进程堆分配的CRT版本。这解决了这个特定问题,而不是其他运行时函数的全局状态问题的解决方法。并增加了一些新问题,例如,使用/MT 编译的 DLL 被卸载但未释放其所有分配现在会导致无法插入的泄漏。
这是 C++ 中的一个丑陋问题,该语言从根本上缺少解决此类问题的 ABI 规范。语言规范中完全没有模块的概念。今天正在处理但尚未完成。做起来并不简单,在其他语言如Java和.NET语言中通过指定一个虚拟机来解决,提供一个集中管理内存的运行环境。不是那种让 C++ 程序员兴奋的运行时环境。
关于c++ - 内联类构造器避免vc内存崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16736195/
作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代
为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
当我在Rails控制台中按向上或向左箭头时,出现此错误:irb(main):001:0>/Users/me/.rvm/gems/ruby-2.0.0-p247/gems/rb-readline-0.4.2/lib/rbreadline.rb:4269:in`blockin_rl_dispatch_subseq':invalidbytesequenceinUTF-8(ArgumentError)我使用rvm来管理我的ruby安装。我正在使用=>ruby-2.0.0-p247[x86_64]我使用bundle来管理我的gem,并且我有rb-readline(0.4.2)(人们推荐的最少
ruby如何管理内存。例如:如果我们在执行过程中采用C程序,则以下是内存模型。类似于这个ruby如何处理内存。C:__________________|||stack|||------------------||||------------------|||||Heap|||||__________________|||data|__________________|text|__________________Ruby:? 最佳答案 Ruby中没有“内存”这样的东西。Class#allocate分配一个对象并返回该对象。这就是程序
我正在处理旧代码的一部分。beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)endRubocop错误如下:Avoidstubbingusing'allow_any_instance_of'我读到了RuboCop::RSpec:AnyInstance我试着像下面那样改变它。由此beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)end对此:let(:sport_
如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:
我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我
你好,我无法成功如何在散列中删除key后释放内存。当我从哈希中删除键时,内存不会释放,也不会在手动调用GC.start后释放。当从Hash中删除键并且这些对象在某处泄漏时,这是预期的行为还是GC不释放内存?如何在Ruby中删除Hash中的键并在内存中取消分配它?例子:irb(main):001:0>`ps-orss=-p#{Process.pid}`.to_i=>4748irb(main):002:0>a={}=>{}irb(main):003:0>1000000.times{|i|a[i]="test#{i}"}=>1000000irb(main):004:0>`ps-orss=-p
我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“