關於編譯器的一個問題

來源:互聯網
上載者:User

 

       今天看了下@leekayak 提到的一個問題 http://weibo.com/1465082730/znOSZzU4v

       我試圖用一個簡單的例子來解釋下,首先看一段更簡單的代碼。

      

#include "stdio.h"#include "stdlib.h"#include <pthread.h>int f = 0;int x=  0;void* t1(void*){        while(f==0)        {                if(x!=0) printf("error");        }        return NULL;};void* t2(void*){        x=1;        f=1;        return NULL;};int main(void){         pthread_t* worker =  (pthread_t*) malloc(2*sizeof( pthread_t));         pthread_create(&worker[0],NULL,t1,NULL);         pthread_create(&worker[1],NULL,t2,NULL);         pthread_join(worker[0],NULL);         pthread_join(worker[1],NULL);         free(worker);        return 0;}

 我們用-O3 來編譯,就發現問題了。編譯器版本:gcc version 4.7.2 20120921 (Red Hat 4.7.2-2) (GCC)

   

在400788:處發現指令自己jmp到自己(_z2t1pv+0x18) = 400770+18 =  400788 就死迴圈了。

這是因為在t1這個函數的局部,看不到f被改變的期望,因此編譯器就自作主張認為f不會變化,等價於死迴圈,其實這個等價是錯誤的,因為f可能被外部修改。比如t2

 

因此就這個case,將f的定義 加上volatile是一個簡明的法子,volatile int f = 0; 聲明了編譯器不能假設f值會是什麼,而是必須去read一下才行。

 

另外的方法就是顯示的加入memory barrier,強制編譯器必須讀取。

while(f==0) { if(x!=0) printf("error"); }

改成

for(__sync_synchronize();f==0;__sync_synchronize())

{

        if(x!=0) printf("error");

}

 

 

                                                                                                                                                        

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.