1

私のコードはデバッグ モードでは問題なく動作しますが、リリース モードでは失敗します。

失敗したコードのスニペットを次に示します。

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

AllocBundle() は m_InitialContent に含まれるコンテンツをロードし、完了すると準備完了ステータスを true に設定します。これは、マルチスレッドを使用して実装されます。

this->LoadingScreen()ロード画面をレンダリングする必要がありますが、現時点ではまだ実装されていないため、関数の本体は空です。

どうやらこれがエラーの原因である可能性があります。関数 LoadingScreen() に 1 行のコードを指定すると、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

コードをデバッグ モードでコンパイルすると、コンパイラは舞台裏で多くのことを行い、プログラマーが犯した多くのミスによってアプリケーションがクラッシュするのを防ぎます。リリースで実行すると、すべての賭けがオフになります。コードが正しくない場合、デバッグよりもリリースでクラッシュする可能性が高くなります。

いくつかの確認事項:

  1. すべての変数が適切に初期化されていることを確認してください
  2. デッドロックや競合状態がないことを確認してください
  3. 割り当てが解除されたローカル オブジェクトへのポインターを渡していないことを確認します。
  4. 文字列が適切に NULL で終了していることを確認してください
  5. 予期しないcatch例外を発生させず、何も起こらなかったかのように実行を続けます。
于 2012-05-10T14:44:48.770 に答える
4

m_bIsReadyメモリバリアなしで異なるスレッドから変数にアクセスしています。オプティマイザまたはプロセッサ キャッシュのいずれかによってキャッシュされる可能性があるため、これは誤りです。CriticalSection、mutex、またはライブラリで利用可能な同期プリミティブとの同時アクセスからこの変数を保護する必要があります。

さらに間違いがあるかもしれないことに注意してください。しかし、これも間違いなく間違いです。経験則として、異なるスレッドからアクセスされる各変数は、ミューテックス/クリティカル セクションなどで保護する必要があります。

于 2012-05-10T15:13:15.843 に答える
0

ざっと見たm_NumRunningThrdsだけでは、同時アクセスから保護されていないように見えるので、if (pCBA->m_NumRunningThrds == 0)決して満足できないかもしれません。

于 2012-05-10T15:00:21.513 に答える