从参考向量获取SEGFAULT

时间:2018-07-19 12:18:06

标签: c++ vector segmentation-fault sfml

问题:

所以,我一直把头撞在墙上。我有一个可以在OSX和Linux上正常运行的应用程序,但是当我在Windows上使用MingW64进行编译时,在运行时会出现SEGFAULT。所以这是发生了什么

我有一个包含std::vector<Tilesheet*> m_tilesheets的Map类。我通过引用构造函数将此变量传递给另一个类MapLayer:

    MapLayer::MapLayer(std::vector<unsigned int>& p_data,
                   std::vector<MindTrip::Graphics::TileSheet*>& p_tilesheets)
        : m_data(p_data),
          m_tilesheets(p_tilesheets)
{
    DrawTexture();
}

向量将作为参考存储在MapLayerClass std::vector<MindTrip::Graphics::TileSheet*>& m_tilesheets;

如果我在该构造函数的第一行上放置一个断点,则m_tilesheets具有_M_First的已定义值。如果将断点放在构造函数的最后一行,则m_tilesheets不再为_M_First定义值。我没有进行多线程处理,并且应用程序尚未离开定义这些变量的范围。

在其下一个名为DrawTexture()的函数中,有一个遍历m_tilesheets的foreach循环,不断为我提供SEGFAULT:

void MapLayer::DrawTexture() {
    for(unsigned int tile_val: m_data)
    {
        // SEGFAULT ON THIS LINE
        for(MindTrip::Graphics::TileSheet* tileSheet : m_tilesheets)
        {

        }
    }
}`

这是我尝试过的:

我尝试将其转换为常规的for循环,但仍然遇到相同的问题。

我尝试使用引用通过将foreach循环转换为向量来获取对象: for(auto& tileSheet : m_tilesheets)。同样的问题

如果我将m_tilesheets从MapLayer类及其构造函数中移出,并将其作为参数传递给DrawTexture作为引用,则将其传递给参数:

MapLayer::DrawTexture(std::vector<MindTrip::Graphics::TileSheet*>& p_tilesheets)

M_data开始在其foreach循环中引发段错误。这很奇怪,因为m_data的foreach循环实际上发生在m_tilesheet的行之前:for(unsigned int tile_val: m_data)

因此,为响应该问题,我尝试将m_data移动到DrawTexture的参数并将其作为成员移除,就像我对m_tilesheets所做的一样,通过引用传递:

MapLayer::DrawTexture(std::vector<MindTrip::Graphics::TileSheet*>& p_tilesheets, std::vector<unsigned int>& p_data)

在我尝试此操作时,我使用的是for循环而不是foreach。 p_tilesheets中应该有1个条目,p_data中应该有10000个条目。这次段错误发生在我正在使用p_tilesheet[j]; j访问p_tilsheet的数据的行上,该行未超出范围,并设置为0。

尝试了所有这些之后,我将代码重置为原来的样子,而是决定也许我将使用std :: copy()复制向量中的数据,而不仅仅是使用类中的引用,为m_tilesheets和m_data实例化新变量。我将foreach切换回常规的for循环,然后再次出现段错误访问m_tilesheets的元素[j]。

我对记忆力到底是怎么回事感到困惑。在访问m_tilesheets和m_data时,它们不为null,并且甚至在构造函数结束之前,它们的_M_First属性也会被取消设置。

同样,仅在Windows上发生。 OSX和Linux可以正常工作。在实现地图类之前,该应用程序在Windows上运行良好。不仅仅是寻找解决方案作为答案,还包括发生此错误的原因。

编辑:

这里是Map的构造函数,我在其中定义这些值并将其传递给MapLayer的新实例。

Map::Map(const char* p_map_file)
{
         m_tile_sheets.push_back(new MindTrip::Graphics::TileSheet("PathToTilesheet", 0));

        std::vector<unsigned int> data(10000, 50);
        m_layers.push_back(new MapLayer(data, m_tile_sheets));
}

1 个答案:

答案 0 :(得分:5)

您提供的代码中没有出现您的问题。这段代码只是触发了该错误。同样(正如其他人所指出的那样),您的代码在Linux&OSX上无法正常工作,只是没有表现出该错误。

由于您也在Linux上进行编译,因此建议您通过valgrind运行代码,并扫描输出以查找未初始化的变量,缓冲区溢出等。 要启动它,您可以使用以下命令:

valgrind --tool=memcheck --track-origins=yes --log-file=log.txt your_prog arg arg

完成调整后,您将在log.txt中包含(大量)数据要检查。您的问题几乎肯定会显示出来。

除此之外,我想问你为什么要使用原始指针?如果您没有很好的理由,我建议您使用其他方法(例如,TileSheets / MapLayers的智能指针,以及std :: string代替char *)。裸露的指针是创建此类错误的“最快方法”。