我有单例类,旨在用于一个线程(GUI 线程),
为了防止错误使用,我添加了 assert
//header file
class ImageCache final {
public:
ImageCache(const ImageCache &) = delete;
ImageCache &operator=(const ImageCache &) = delete;
static ImageCache &instance()
{
static ImageCache cache;
return cache;
}
void f();
private:
QThread *create_context_ = nullptr;
ImageCache();
};
//cpp
ImageCache::ImageCache()
{
create_context_ = QThread::currentThread();
qInfo("begin, cur thread %p\n", create_context_);
}
void ImageCache::f()
{
assert(create_context_ == QThread::currentThread());
}
一切正常,但在一台机器上 ImageCache::f 断言失败,
我无法直接访问那台机器(因此出现了这个问题)。
有趣的是,根据日志 ImageCache::ImageCache
根本没有被调用,断言失败是因为
assert(0 == QThread::currentThread());
我将 ImageCache::instance 的实现从头文件移动到 .cpp 文件,
将更新后的源代码发送给这些机器的用户(我的一切正常),
他重建并按预期开始工作。
我向他询问已编译的二进制文件(有断言失败和没有断言失败),它们之间的唯一区别是 ImageCache::instance 实现的位置,
并比较汇编器。
调用 ImageInstance::instance().f() 没有区别
根本,
ImageInstance::instance 的反汇编器有一个区别,
失败的看起来像这样:
static ImageCache &instance()
4938f: 55 push %rbp
49390: 48 89 e5 mov %rsp,%rbp
49393: 41 54 push %r12
49395: 53 push %rbx
{
static ImageCache cache;
49396: 48 8b 05 bb db 23 00 mov 0x23dbbb(%rip),%rax # 286f58 <_ZGVZN10ImageCache8instanceEvE5cache@@Base-0x2150>
4939d: 0f b6 00 movzbl (%rax),%eax
493a0: 84 c0 test %al,%al
493a2: 0f 94 c0 sete %al
493a5: 84 c0 test %al,%al
493a7: 74 5c je 49405 <_ZN10ImageCache8instanceEv+0x76>
493a9: 48 8b 05 a8 db 23 00 mov 0x23dba8(%rip),%rax # 286f58 <_ZGVZN10ImageCache8instanceEvE5cache@@Base-0x2150>
493b0: 48 89 c7 mov %rax,%rdi
493b3: e8 08 b7 fe ff callq 34ac0 <__cxa_guard_acquire@plt>
好的是这样的:
ImageCache &ImageCache::instance()
{
50c12: 55 push %rbp
50c13: 48 89 e5 mov %rsp,%rbp
50c16: 41 54 push %r12
50c18: 53 push %rbx
static ImageCache cache;
50c19: 0f b6 05 98 94 23 00 movzbl 0x239498(%rip),%eax # 28a0b8 <_ZGVZN10ImageCache8instanceEvE5cache>
50c20: 84 c0 test %al,%al
50c22: 0f 94 c0 sete %al
50c25: 84 c0 test %al,%al
50c27: 74 50 je 50c79 <_ZN10ImageCache8instanceEv+0x67>
50c29: 48 8d 3d 88 94 23 00 lea 0x239488(%rip),%rdi # 28a0b8 <_ZGVZN10ImageCache8instanceEvE5cache>
50c30: e8 cb 3d fe ff callq 34a00 <__cxa_guard_acquire@plt>
区别在于
//bad
mov 0x23dbbb(%rip),%rax
movzbl (%rax),%eax
//good
movzbl 0x239498(%rip),%eax
我的解释是,出于某种原因,第一个变体的 %eax 寄存器得到了错误的值,因此决定全局对象在未初始化时被初始化。在第二种情况下,一切都按预期工作。
那么是编译器失败 (gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0/amd64/linux) 还是我应该在 .cpp 出于某种原因,
还是其他导致代码生成不同的原因,例如某些编译器错误可能导致此失败?代码是使用 -O0 -std=c++11 和 cmake 在编译依赖于 Qt 库的共享库时自动添加的一些其他标志编译的。
我还询问使用 fprintf(stderr 而不是 qInfo 的测试代码,
并且用户在第二种情况下看到输出,而在第一种情况下看不到输出。
最佳答案
原始答案
据我了解,头文件中的函数存在的问题是您可以获得多个定义,然后行为未指定。
从本质上讲,编译器可能会生成多个函数 instance,每个包含该 header 的编译单元都有一个,因此如果它们在链接时没有合并/消除,每个函数都会有自己的变量.
在 Windows 中,如果我们在多个 DLL 中编译相同的代码,其中某些变量在每个动态库中重复,我们可能会遇到类似的问题。
然后会发生的情况是,因为每个客户端都有自己的拷贝,一个客户端所做的更改不会被另一个翻译单元(您的问题)或另一个 DLL(我的问题)中的另一个客户端看到。
通过将定义移动到源文件中,您将得到一个单一的定义,从而避免了这个问题。
在C++中,如果你不遵循规范,你经常会得到未定义的行为。程序员知道他在做什么。
更新
如前所述,在评论中,根据当前标准,我的假设可能是错误的。因此,问题也可能是过时的编译器或编译器错误。
对正在发生的事情的可能解释:
在许多情况下,当编译器合并重复项时,代码将是相同的,因此选择哪个代码不会有任何区别。在这里,假设编译器为静态变量分配了 2 个不同的地址(每个编译单元一个)并以某种方式内联对 instance() 的调用,它使用原始变量而不是合并的变量(选择)一个,它可以解释观察到的行为。
关于c++ - 没有调用单例的构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53841757/
我好像记得Lua有类似Ruby的method_missing的东西。还是我记错了? 最佳答案 表的metatable的__index和__newindex可以用于与Ruby的method_missing相同的效果。 关于ruby-难道Lua没有和Ruby的method_missing相媲美的东西吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/7732154/
我有一个奇怪的问题:我在rvm上安装了rubyonrails。一切正常,我可以创建项目。但是在我输入“railsnew”时重新启动后,我有“程序'rails'当前未安装。”。SystemUbuntu12.04ruby-v"1.9.3p194"gemlistactionmailer(3.2.5)actionpack(3.2.5)activemodel(3.2.5)activerecord(3.2.5)activeresource(3.2.5)activesupport(3.2.5)arel(3.0.2)builder(3.0.0)bundler(1.1.4)coffee-rails(
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re
我正在尝试用ruby中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了
我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file
我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin
如何在ruby中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL
我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www
我需要一些关于TDD概念的帮助。假设我有以下代码defexecute(command)casecommandwhen"c"create_new_characterwhen"i"display_inventoryendenddefcreate_new_character#dostufftocreatenewcharacterenddefdisplay_inventory#dostufftodisplayinventoryend现在我不确定要为什么编写单元测试。如果我为execute方法编写单元测试,那不是几乎涵盖了我对create_new_character和display_invent