简体   繁体   English

C ++是什么会导致一行代码在一个地方更改无关功能的行为?

[英]C++ What could cause a line of code in one place to change behavior in an unrelated function?

Consider this mock-up of my situation. 考虑一下我的情况。

in an external header: 在外部标题中:

class ThirdPartyObject
{
    ...
}

my code: (spread among a few headers and source files) 我的代码:(分布在一些头文件和源文件中)

class ThirdPartyObjectWrapper
{
private:
    ThirdPartyObject myObject;
}

class Owner
{
public:
    Owner() {}
    void initialize();

private:
    ThirdPartyObjectWrapper myWrappedObject;
};

void Owner::initialize()
{
    //not weird:
    //ThirdPartyObjectWrapper testWrappedObject;

    //weird:
    //ThirdPartyObject testObject;

}

ThirdPartyObject is, naturally, an object defined by a third party (static precompiled) library I'm using. ThirdPartyObject自然是由我使用的第三方(静态预编译)库定义的对象。 ThirdPartyObjectWrapper is a convenience class that eliminates a lot of boiler-plating for working with ThirdPartyObject. ThirdPartyObjectWrapper是一个便利类,可消除使用ThirdPartyObject的大量重复步骤。 Owner::initialize() is called shortly after an instance of Owner is created. 业主::初始化()被调用时创建者的实例不久。

Notice the two lines I have labeled as "weird" and "not weird" in Owner::initialize(). 注意在Owner :: initialize()中,我标记为“奇怪”和“不奇怪”的两行。 All I'm doing here is creating a couple of objects on the stack with their default constructors. 我在这里所做的就是使用默认构造函数在堆栈上创建几个对象。 I don't do anything with those objects and they get destroyed when they leave scope. 我对那些对象不做任何事情,它们在离开范围时被破坏了。 There are no build or linker errors involved, I can uncomment either or both lines and the code will build. 没有构建或链接器错误,我可以取消注释其中任一行,也可以取消注释这两行,然后将构建代码。

However, if I uncomment "weird" then I get a segmentation fault, and (here's why I say it's weird) it's in a completely unrelated location. 但是,如果我取消注释“怪异”,则会遇到分段错误,并且(这就是为什么我说这很奇怪)它位于完全不相关的位置。 Not in the constructor of testObject, like you might expect, but in the constructor of Owner::myObjectWrapper::myObject . 如您所料,不是在testObject的构造函数中, 而是在Owner :: myObjectWrapper :: myObject的构造函数中 The weird line never even gets called, but somehow its presence or absence consistently changes the behavior of an unrelated function in a static library. 奇怪的行甚至都没有被调用过,但是以某种方式它的存在或不存在总是会改变静态库中不相关函数的行为。

And consider that if I only uncomment "not weird" then it runs fine, executing the ThirdPartyObject constructor twice with no problems. 考虑一下,如果我只取消注释“ not weird”,那么它将运行良好,两次执行ThirdPartyObject构造函数都没有问题。

I've been working with C++ for a year so it's not really a surprise to me that something like this would be able happen, but I've about reached the limit of my ability to figure out how this gotcha is happening. 我一直用C ++了一年,所以它不是一个真正的惊喜,我认为这样的事情会发生的能力,但我已经约到了我要弄清楚如何疑难杂症正在发生能力的极限。 I need the input of people with significantly more C++ experience than me. 我需要比我有很多C ++经验的人的意见。

What are some possibilities that could cause this to happen? 有什么可能导致这种情况发生? What might be going on here? 这可能是怎么回事?

Also, note, I'm not asking for advice on how to get rid of the segfault. 另外,请注意,我并不是在寻求有关如何消除段错误的建议。 Segfaults I understand, I suspect it's a simple race condition. 我了解Segfault,我怀疑这是一个简单的比赛条件。 What I don't understand is the behavior gotcha so that's the only thing I'm trying to get answers for. 我不理解的是行为陷阱,所以这是我唯一想要获得答案的东西。

My best lead is that it has to do with headers and macros. 我最好的线索是,它与标头和宏有关。 The third party library actually already has a couple of gotchas having to do with its headers and macros, for example the code won't build if you put your #include's in the wrong order. 第三方库实际上已经有一些与其标题和宏有关的陷阱,例如,如果您将#include的顺序错误,将无法构建代码。 I'm not changing any #include's so strictly this still wouldn't make sense, but perhaps the compiler is optimizing includes based on the presence of a symbol here? 我没有更改任何#include,以至于严格来说这仍然没有意义,但也许编译器正在根据此处是否存在符号来优化include? (it would be the only mention of ThirdPartyObject in the file) (这是文件中对ThirdPartyObject的唯一提及)

It also occurs to me that because I am using Qt, it could be that the Meta-Object Compiler (which generates supplementary code between compilations) might be involved in this. 我还想到,由于我使用的是Qt,因此可能涉及到元对象编译器(在编译之间生成补充代码)。 Very unlikely, as Qt has no knowledge of the third party library where the segfault is happening and this is not actually relevant to the functionality of the MOC (since at no point ThirdPartyObject is being passed as an argument), but it's worth investigating at least. Qt不太可能,因为Qt不知道发生段错误的第三方库,而这实际上与MOC的功能无关(因为从没有将ThirdPartyObject作为参数传递),但是至少值得研究一下。

Related questions have suggested that it could be a relatively small buffer overflow or race condition that gets tripped up by compiler optimizations. 相关问题表明,可能是编译器优化使缓冲区溢出或竞争条件相对较小。 Continuing to investigate but all leads are welcome. 继续进行调查,但欢迎所有潜在客户。

Typical culprits: 典型罪魁祸首:

  1. Some build products are stale and not binary-compatible. 一些构建产品是过时的,并且不是二进制兼容的。

  2. You have a memory bug that has corrupted the state of your process, and are seeing a manifestation of that in a completely unrelated location. 您有一个内存错误,损坏了您的进程状态,并在完全不相关的位置看到了该错误的体现。

Fixing #1 is trivial: delete the build folder and build again. 修复#1很简单:删除build文件夹并重新构建。 If you're not building in a shadow build folder, you've set yourself up for failure, hopefully you now know enough to stop :) 如果您不是在shadow build文件夹中进行构建,则说明您已经失败了,希望您现在知道足以阻止它了:)

Fixing #2 is not trivial. 修复#2并非易事。 View manual memory management and possible buffer overflows with suspicion. 怀疑查看手动内存管理和可能的缓冲区溢出。 Use modern C++ programming techniques to leverage the compiler to help you out: store things by value, use containers, use smart pointers, and use iterators and range-for instead of pointers. 使用现代C ++编程技术来利用编译器为您提供帮助:按值存储内容,使用容器,使用智能指针以及使用迭代器和range-for代替指针。 Don't use C-style arrays. 不要使用C样式的数组。 Abhor C-style APIs of the (Type * array, int count) kind - they don't belong in C++. (Type * array, int count)类型的Abhor C样式API-它们不属于C ++。

What fun. 真有趣 I've boiled this down to the bottom. 我把它煮到最底层了。

//#include <otherthirdpartyheader.h>
#include <thirdpartyobject.h>

int main(...)
{
    ThirdPartyObject test;
    return 0;
}

This code runs. 此代码运行。 If I uncomment the first include, delete all build artifacts, and build again, then it breaks. 如果我取消对第一个包含的注释,请删除所有构建工件,然后重新构建,然后它将中断。 There's obviously a header/macro component, and probably some kind of compiler-optimization component. 显然有一个标头/宏组件,可能还有某种编译器优化组件。 But, get this, according to the library documentation it should give me a segfault every time because I haven't been doing a required initialization step. 但是,要做到这一点,根据库文档,每次都应该给我一个段错误,因为我没有执行必需的初始化步骤。 So the fact that it runs at all indicates unexpected behavior. 因此,它完全运行这一事实表明存在意外行为。

I'm chalking this up to library-specific issues rather than broad spectrum C++ issues. 我将其归因于特定于库的问题,而不是广泛的C ++问题。 I'll be contacting the vendor going forward from here, but thanks everyone for the help. 从现在开始,我将与供应商联系,但感谢大家的帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 什么可能导致返回功能崩溃? C ++ - What could cause a returning function to crash? C++ C++ 这个 function 会导致未定义的行为吗? - C++ does this function cause a undefined behavior? 一个函数中的局部变量改变导致一个不相关的函数C ++ - Local variable in one function changing results in an unrelated function, C++ 为什么在一行中两次使用此C ++函数会导致编译错误? - Why does using this C++ function twice in one line cause a compile error? 什么会导致 C++ 对象的类型信息在从 function 返回后发生变化? - What would cause a C++ object's type information to change after it is returned from a function? 什么 C++ 设计模式可用于在生产代码和测试代码之间交换函数模板的行为? - What C++ design pattern is available for swapping behavior of a function template between production code and testing code? 什么可能导致此代码段错误 - What could cause this code to segfault 从 C++ 中不相关的函数访问变量 - Accessing a variable from an unrelated function in C++ C ++:当我添加看似无关的代码行时,分段错误消失了 - C++: Segmentation Fault Goes Away When I Add a Seemingly Unrelated Line of Code 我可以在 C++ 中使用哪一行代码来禁用节能器? - What line of code could I use in C++ to disable energy saver?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM