gpt4 book ai didi

c++ - 在从全局对象调用的静态库函数中使用 std::vector 时调试断言失败

转载 作者:行者123 更新时间:2023-11-30 01:28:59 25 4
gpt4 key购买 nike

我目前正在清理我的解决方案的代码,该解决方案由一个静态库和两个依赖它的应用程序组成。作为此代码清理的一部分,我一直在将我在 std::vectors 上的所有循环转换为使用迭代器而不是索引。一切都很顺利,直到我转换了一个在构建全局对象(在应用程序中)期间调用的函数(在库中)。有问题的函数填充一个 std::vector,然后在 vector 中搜索与传递给函数的描述相匹配的对象,返回第一个匹配项。如果没有找到匹配项,则返回 vector 的前面。

我已经设法将问题简化为以下代码:

库 - Bar.h

struct Bar
{
int val;

Bar(int val = 0);

static Bar const& ByVal(int val);
};

库 - Bar.cpp

#include "Bar.h"
#include <vector>

using namespace std;

namespace { vector<Bar> bars; } // It is irrelevant whether bars is in an
// anonymous namespace or not; the results are
// the same.

Bar::Bar(int _val) : val(_val) { }

Bar const& Bar::ByVal(int val)
{
if (bars.empty())
{
bars.push_back(Bar(1));
bars.push_back(Bar(2));
}

#if 1
for (vector<Bar>::const_iterator it = bars.begin();
it != bars.end();
++it) // The assertion fails here. However, when the for loop is
// replaced with a while loop, it's the it != bars.end() part
// that fails.
{
if (it->val == val)
return *it;
}

return bars.front();
#else
for (size_t i = 0;
i < bars.size();
++i)
{
if (bars[i].val == val)
return bars[i];
}

return bars[0];
#endif
}

应用程序 - Foo.cpp

#include <Bar.h>
#include <iostream>

using namespace std;

struct Foo
{
Foo()
{
Bar bar = Bar::ByVal(0);
cout << bar.val << endl;
}
};

Foo foo;

int main(int argc, char** argv)
{
return 0;
}

如果 Bar.cpp 中的预处理器条件更改为 0,代码将完美执行。否则,将显示以下断言:

Debug Assertion Failed!

Program: C:\Work\Reduction\Debug\Foo.exe
File: c:\program files (x86)\microsoft visual studio 10.0\vc\include\vector
Line: 238

Expression: vector iterators not compatible

这是在 Visual Studio 2010 中使用全新项目的全新解决方案。项目中唯一更改的设置是让应用程序链接到静态库所必需的设置。

为了找出导致崩溃的原因,我发现代码在以下条件下有效:

  • 在 Release模式下编译时。
  • 当库的 bars vector 声明为 extern,并在应用程序本身中定义时。
  • 当应用程序的 foo 变量移入 main() 函数时。
  • 当库中的代码完全移至应用程序时。
  • 在 Visual Studio 2008 下编译时。

任何帮助将不胜感激,即使这意味着返回使用索引或 VS2008。近两天来,我一直在疯狂地搜索和思考这个问题。

最佳答案

C++ 标准不保证 bars 的构造函数会在 foo 之前被调用。这有时称为 'static initialization order fiasco' ;你可能会在 VS2008 中走运,但这并不意味着问题就消失了。链接的页面针对此问题提出了一些可能的解决方案,其中之一是使用函数级静态来确保它在使用前进行初始化。

关于c++ - 在从全局对象调用的静态库函数中使用 std::vector 时调试断言失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6727119/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com