1

我的代码在调试模式下运行良好,但在发布模式下失败。

这是我失败的代码片段:

LOADER->AllocBundle(&m_InitialContent);
while(!m_InitialContent.isReady())
{
    this->LoadingScreen();
}

AllocBundle() 将加载包含在 m_InitialContent 中的内容,并在完成后将其就绪状态设置为 true。这是使用多线程实现的。

this->LoadingScreen()应该呈现一个加载屏幕,但是目前尚未实现,因此该函数有一个空的主体。

显然这可能是错误的原因:如果我给函数 LoadingScreen() 一行代码:std::cout<<"Loading"<<std::endl;那么它将运行良好。

如果我不这样做,那么代码就会卡在while(!m_InitialContent.isReady())它甚至不会跳转到括号 ( this->LoadingScreen();) 之间的代码。显然它也不会更新 while 语句中的表达式,因为它永远停留在那里。

有谁知道可能是什么原因造成的?如果是这样,问题可能是什么?我完全不解。


编辑:应要求提供附加代码

ContentLoader 的成员:details::ContentBundleAllocator m_CBA;

    void ContentLoader::AllocBundle(ContentBundle* pBundle)
    {
        ASSERT(!(m_CBA.isRunning()), "ContentBundleAllocator is still busy");
        m_CBA.Alloc(pBundle, m_SystemInfo.dwNumberOfProcessors);
    }

void details::ContentBundleAllocator::Alloc(ContentBundle* pCB, UINT numThreads)
{
    m_bIsRunning = true;
    m_pCB = pCB;
    pCB->m_bIsReady = false;


    m_NumRunningThrds = numThreads;
    std::pair<UINT,HANDLE> p;
    for (UINT i = 0; i < numThreads; ++i)
    {
        p.second = (HANDLE)_beginthreadex(NULL,
                                          NULL,
                                          &details::ContentBundleAllocator::AllocBundle,
                                          this,
                                          NULL,&p.first);
        SetThreadPriority(p.second,THREAD_PRIORITY_HIGHEST);
        m_Threads.Insert(p);
    }
}

unsigned int __stdcall details::ContentBundleAllocator::AllocBundle(void* param)
{
//PREPARE
    ContentBundleAllocator* pCBA = (ContentBundleAllocator*)param;

//LOAD STUFF [collapsed for visibility+]

   //EXIT===========================================================================================================
        pCBA->m_NumRunningThrds -= 1;
        if (pCBA->m_NumRunningThrds == 0)
        {
            pCBA->m_bIsRunning = false;
            pCBA->m_pCB->m_bIsReady = true;
            pCBA->Clear();
    #ifdef DEBUG
            std::tcout << std::endl;
    #endif
            std::tcout<<_T("exiting allocation...")<<std::endl;
        }

    std::tcout<<_T("exiting thread...")<<std::endl;
    return 0;
}

bool isReady() const {return m_bIsReady;}
4

3 回答 3

7

当您在调试模式下编译代码时,编译器会在幕后做很多事情,以防止程序员犯的许多错误导致应用程序崩溃。当您在 Release 中运行时,所有赌注都已取消。如果您的代码不正确,那么您在 Release 中崩溃的可能性比在 Debug 中要大得多。

需要检查的几件事:

  1. 确保所有变量都正确初始化
  2. 确保您没有任何死锁或竞争条件
  3. 确保您没有传递指向已被释放的本地对象的指针
  4. 确保您的字符串正确地以 NULL 结尾
  5. 不要出现catch您没有预料到的异常,然后继续运行,就好像什么都没发生一样。
于 2012-05-10T14:44:48.770 回答
4

您正在m_bIsReady从没有内存障碍的不同线程访问变量。这是错误的,因为它可能被优化器或处理器缓存缓存。您必须保护此变量免于同时访问 CriticalSection、互斥锁或您的库中可用的任何同步原语。

请注意,可能还有更多错误,但这也绝对是一个错误。根据经验:从不同线程访问的每个变量都必须使用互斥锁/临界区/其他方式进行保护。

于 2012-05-10T15:13:15.843 回答
0

快速浏览似乎m_NumRunningThrds并没有受到同时访问的保护,因此if (pCBA->m_NumRunningThrds == 0)可能永远不会满足。

于 2012-05-10T15:00:21.513 回答