簡體   English   中英

為什么插入printf語句會使我的函數正常工作?

[英]Why does inserting a printf statement make my function work correctly?

這是我的代碼的基本前提:

while(norm_of_error > tol){
  #pragma omp parallel for
  for(i = 1; i <= N*N; i++){
    //printf("thread id: %d\n",omp_get_thread_num());
      :
    int val = based on i
      :
    #pragma omp critical
    x[i-1] = val;
  }
  #pragma omp barrier
  iter++;
}

簡而言之,我使用Jacobi迭代方法求解Ax = b。 我的問題是,在取消注釋printf()語句的情況下, norm_of_error趨於零並且while循環結束。 但是,通過簡單地注釋掉printf()語句,就不會發生這種情況。 任何人都可以給我一個提示,為什么printf()語句有任何影響? 我猜這個問題與omp_get_thread_num()的調用有關,但我不明白為什么會有任何區別。

編輯:我將printf()語句更改為printf("hi\\n"); 並且代碼有效。 注釋出來,代碼不起作用。

printf()語句一起使用但在刪除時失敗的代碼通常是某些無效操作的標志,這些操作會影響某個程序中的內存(例如,從數組的末尾掉下來,取消引用NULL等)。 行為不當的代碼可能完全在程序的其他部分(例如,不在包含printf()語句的函數內)

當違規的printf()聲明顯然是無辜的,並且沒有任何可能影響其他代碼行為的副作用(例如printf("Hi\\n") )時,這更有可能發生。

原因是額外的printf()存在實際上影響了整個程序的內存布局。 因此,違規代碼(可能在程序中某些完全不相關的部分)仍會覆蓋內存,但結果會發生變化(例如,覆蓋某些數據,允許程序更改,而不是導致操作系統終止的某些內存區域)該程序)。

無論代碼是否為多線程,都是如此。

如果沒有完整的代碼來說明問題(即其他人可以編譯,構建和運行以獲得相同症狀的小樣本),則不可能更具體。

您還沒有發布您的代碼,因此我們無法確切知道,但這通常是因為您嘗試在線程之間共享數據而未充分指示要共享數據。

刪除printf后,程序將數據加載到寄存器中,當它再次需要數據時,它會記住寄存器中的值而不是再次從內存中取出它,因此它看不到其他線程可能發生的任何更改取得了。

使用printf ,你的程序不會將數據保存在寄存器中 - 也許它不能以這種方式使用寄存器,或者它無法確定函數調用無法更改數據(當然,它只是printf ,但它可能不是特殊的,即使它是,編譯器更好地找到可能允許printf更改數據的漏洞) - 所以它在調用printf后重新讀取內存中的數據,因此可以看到在其他線程中進行的任何先前更改。

printf可以改變的另一個方面是時間:與計算相比,I / O語句非常慢,並且I / O庫中可能會發生一些同步; 您的print可能會起到阻止競爭條件發生的偽障礙的作用。

請記住,C和C ++是不同的語言

C FAQ有關於奇怪問題的部分:

comp.lang.c常見問題列表·問題16.5

問:這個程序在一台機器上運行完美,但我在另一台機器上得到了奇怪的結果。 更奇怪的是,添加或刪除調試打印輸出會改變症狀......

答:很多事情都可能出錯; 這里有一些比較常見的事情要檢查:

  • 未初始化的局部變量[腳注](另見問題7.1)
  • 整數溢出,特別是在16位機器上,特別是在執行像* b / c這樣的事情時的中間結果(另見問題3.14)
  • 未定義的評估順序(見問題3.1至3.4)
  • 省略外部函數的聲明,特別是那些返回int以外的函數,或者有``narrow''或變量參數的函數(參見問題1.25,11.3,14.2和15.1)
  • 解除引用的空指針(參見第5節)
  • 不正確的malloc /免費使用:假設malloc的內存包含0,假設釋放存儲持續存在,釋放兩次,破壞malloc競技場(另見問題7.19和7.20)
  • 指針問題一般(另見問題16.7和16.8)
  • printf格式和參數之間不匹配,尤其是嘗試使用%d打印長整數(參見問題12.7和12.9)
  • 嘗試分配比unsigned int更多的內存可以計算,特別是在內存有限的機器上(參見問題7.16和19.23)
  • 數組邊界問題,特別是小的臨時緩沖區,可能用於使用sprintf構造字符串[腳注](另見問題7.1,12.21和19.28)
  • 關於typedef映射的無效假設,尤其是size_t(參見問題7.15)
  • 浮點問題(見問題14.1和14.4a)
  • 你認為的任何東西都巧妙地利用了你認為特定系統生成代碼的方式

正確使用函數原型可以捕獲其中的幾個問題; 皮棉會抓到幾個。 另見問題16.3,16.4和18.4。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM