多線程編程時應警惕release 編譯模式

目錄

 

原理

示例

解決


原理

visual studio 提供兩種模式來編譯C++代碼:debug和release.

release 模式下,編譯器會“優化”代碼,把它認爲可以簡化的邏輯簡化掉。比如說以下代碼:

void func()
{
    int i = 1;
    int j;
    j = i;
    while(i == j){}
}

 編譯器看到 i 賦值給 j,而且後來的語句裏 i  j 的值不再變化,於是編譯器將以上代碼簡化爲:

void func()
{
    while(true){}
}

 假如i 和 j 只是局部變量,不受其他線程的操作,那麼這樣的簡化是沒有問題的。但是假如我們進行多線程編程,而且 i j 可以被多個線程操作,則以上簡化會帶來很大的問題。

示例

以下面的代碼作爲簡單的例子來說明:

#include "thrd.h"

Thrd::Thrd(QObject *parent) : QThread(parent)
{
    m_iCount = 0;
    m_bFlag = false;
}

void Thrd::run(void)
{
    m_iCount++;
    while(m_bFlag)
    {}
}

void Thrd::vStart(void)
{
    int iTmp = m_iCount;
    m_bFlag = true;
    start();
    while(m_iCount == iTmp){}
}

void Thrd::vStop(void)
{
    m_bFlag = false;
    while(isRunning()){}
}
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    m_pThrd = new Thrd;
}

MainWindow::~MainWindow()
{
    delete ui;
    m_pThrd->vStop();
    delete m_pThrd;
}

void MainWindow::on_pushButton_clicked()
{
    m_pThrd->vStart();
}

void MainWindow::on_pushButton_2_clicked()
{
    m_pThrd->vStop();
}

在release模式下編譯之後,啓動線程(調用vStart()函數),程序將陷入死循環!原因在前面已經闡述了。

同樣的代碼在debug模式下是不會死循環的。因爲vStart()函數沒有被“優化”。在while(m_iCount == iTmp){}等待之時,子線程也開始運行(run()函數),並且改變了m_iCount的取值,使得while(m_iCount == iTmp)循環得以跳出。

解決

假如項目要求我們必須在release模式下編譯,而且我們需要多線程,該如何處理?

在項目屬性頁選擇C\C++ > 優化 > 優化 > 已禁用(\Od)即可

完整的代碼可以在我的資源>release.rar中下載

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章