Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++;多线程应用程序崩溃 我正在编写一个简单的3D渲染引擎,以便让C++更专业。今天,我开始了多线程处理的第一步,但已经遇到了一个无法解决的问题。当应用程序启动时,它会生成一个由立方体组成的类似地雷的小地形。它们是在主线程中生成的_C++_Multithreading_C++11_Dictionary_Vector - Fatal编程技术网

C++;多线程应用程序崩溃 我正在编写一个简单的3D渲染引擎,以便让C++更专业。今天,我开始了多线程处理的第一步,但已经遇到了一个无法解决的问题。当应用程序启动时,它会生成一个由立方体组成的类似地雷的小地形。它们是在主线程中生成的

C++;多线程应用程序崩溃 我正在编写一个简单的3D渲染引擎,以便让C++更专业。今天,我开始了多线程处理的第一步,但已经遇到了一个无法解决的问题。当应用程序启动时,它会生成一个由立方体组成的类似地雷的小地形。它们是在主线程中生成的,c++,multithreading,c++11,dictionary,vector,C++,Multithreading,C++11,Dictionary,Vector,现在当我想生成更多块时 void VoxelWorld::generateChunk(glm::vec2 chunkPosition) { Chunk* generatedChunk = m_worldGenerator->generateChunk(chunkPosition); generatedChunk->shader = m_chunkShader; generatedChunk->generateRenderObject(); m_c

现在当我想生成更多块时

void VoxelWorld::generateChunk(glm::vec2 chunkPosition) {
    Chunk* generatedChunk = m_worldGenerator->generateChunk(chunkPosition);
    generatedChunk->shader = m_chunkShader;
    generatedChunk->generateRenderObject();
    m_chunks[chunkPosition.x][chunkPosition.y] = generatedChunk;
    m_loadedChunks.push_back(glm::vec2(chunkPosition.x, chunkPosition.y));
}

void VoxelWorld::generateChunkThreaded(glm::vec2 chunkPosition) {
    std::thread chunkThread(&VoxelWorld::generateChunk, this, chunkPosition);
    chunkThread.detach();
}

void VoxelWorld::draw() {
    for(glm::vec2& vec : m_loadedChunks){
        Transformation* transformation = new Transformation();
        transformation->getPosition().setPosition(glm::vec3(CHUNK_WIDTH*vec.x, 0, CHUNK_WIDTH*vec.y));
        m_chunks[vec.x][vec.y]->getRenderObject()->draw(transformation);
        delete(transformation); //TODO: Find a better way
    }
}
我有我的成员函数(一切都是非静态的)
generateChunk()
,它生成块并将其存储在
VoxelWorld
类中。我有一个2D
std::map m_chunks
存储每个块,还有一个
std::vector m_loadedChunks
存储生成块的位置


调用
generateChunk()
工作正常。但是当我尝试
generateChunkThreaded()
时,应用程序崩溃了!我试着注释掉
generateChunk()
的最后一行,然后它就不会崩溃了。这就是让我如此困惑的原因
m_loadedChunks
只是一个普通的std::vector。我试着把它公之于众,但没有效果。我有什么明显的遗漏吗

您正在从多个线程访问m_LoadedChunk,而不同步它。 您需要锁定共享用法的用法。这里没有什么提示

  • 将互斥体声明为类的成员
  • 每次要访问元素时,使用它通过关键部分锁定
  • 标准:锁和防护锁(mtx)

    m_chunks[chunkPosition.x][chunkPosition.y]=generatedChunk

    m_加载chunks.push_back(glm::vec2(chunkPosition.x,chunkPosition.y))


    希望这对您有所帮助

    当您有许多线程访问共享资源时,您可以将这些资源设置为只读、原子或由互斥锁保护

    因此,对于m_loadedChunks成员变量,您希望将其包装在锁中。例如:

    class VoxelWorld
    {
        // your class members and more ...
    private:
      std::mutex m_loadedChunksMutex;
    }
    
    void VoxelWorld::generateChunk(glm::vec2 chunkPosition)
    {
        Chunk* generatedChunk  = m_worldGenerator->generateChunk(chunkPosition);
        generatedChunk->shader = m_chunkShader;
    
        generatedChunk->generateRenderObject();
    
        m_chunks[chunkPosition.x][chunkPosition.y] = generatedChunk;
    
        {
            auto&& scopedLock = std::lock_guard< std::mutex >(m_loadedChunksMutex);
            (void)scopedLock;
            m_loadedChunks.push_back(glm::vec2(chunkPosition.x, chunkPosition.y));
        }
    }
    
    类体素世界
    {
    //你的班级成员和更多。。。
    私人:
    std::mutex m_loadedChunksMutex;
    }
    void VoxelWorld::generateChunk(glm::vec2 chunkPosition)
    {
    Chunk*generatedChunk=m_worldGenerator->generateChunk(chunkPosition);
    generatedChunk->shader=m_chunkShader;
    generatedChunk->generateRenderObject();
    m_chunks[chunkPosition.x][chunkPosition.y]=generatedChunk;
    {
    auto&&scopedLock=std::lock\u guard(m_loadedChunksMutex);
    (无效)scopedLock;
    m_加载chunks.push_back(glm::vec2(chunkPosition.x,chunkPosition.y));
    }
    }
    
    scopedLock将自动等待锁定,当代码超出范围时,锁定将被释放

    现在请注意,我有一个用于m_loadedchunk的互斥锁,而不是一个覆盖线程可能访问的所有变量的通用互斥锁。这实际上是Herb Sutter在他的“有效并发”课程和在cppcon上的演讲中介绍的一个很好的实践


    因此,对于您拥有的任何共享变量,请使用上述示例作为解决争用问题的一种方法。

    我甚至无法发现同步访问
    m_chunks
    m_loadedChunks
    的最小尝试。此外,避免在绘图循环中进行动态分配。@molbdnilo这是一个大问题吗?我是说在那种情况下这有什么关系
    m_loadedChunks
    没有特定的顺序,
    m_chunks
    是一个包含许多映射的映射。我知道我的抽签结果一团糟。这在我的待办事项清单上。你从哪里学习多线程编程?你可能应该为自己准备更好的学习材料。上网。我从来没有吃过比这更好的。好的,谢谢,我试试。但我为什么要把它锁上?@kiryu1。这里的代码太少,无法精确缩小程序崩溃的范围。缺乏并发防御是一个明显的问题,如果它不是当前bug的原因,那么它将成为未来的问题。2.使用互斥锁,但这样你可以得到范围解锁和更少的令人讨厌的惊喜。(待续)。你为什么需要这个?原因之一是:
    m_loadedChunks。当另一个线程正在迭代它时,push_back
    可能会调整
    m_loadedChunks
    的备份数据存储的大小。调整大小的一部分是删除和替换旧的数据存储,因此另一个线程正在查看的数据可能已经消失。它已被一个副本替换,但另一个线程无法知道这一点。您是对的,这是解决问题的第一步。对于lock_-guard,我将使用我的代码,这是真的,但我只缩进使用线程生成地形。至少现在是这样。我不知道这是否合适,但会有一个坏消息。在那里你也可以看到我的头文件。我现在正被这个该死的虫子压碎我的头!编辑此选项时不实际使用互斥。
    class VoxelWorld
    {
        // your class members and more ...
    private:
      std::mutex m_loadedChunksMutex;
    }
    
    void VoxelWorld::generateChunk(glm::vec2 chunkPosition)
    {
        Chunk* generatedChunk  = m_worldGenerator->generateChunk(chunkPosition);
        generatedChunk->shader = m_chunkShader;
    
        generatedChunk->generateRenderObject();
    
        m_chunks[chunkPosition.x][chunkPosition.y] = generatedChunk;
    
        {
            auto&& scopedLock = std::lock_guard< std::mutex >(m_loadedChunksMutex);
            (void)scopedLock;
            m_loadedChunks.push_back(glm::vec2(chunkPosition.x, chunkPosition.y));
        }
    }