2015-12-18 14 views
8

Tôi có đoạn mã này:đang rất kỳ lạ dưới những điều kiện nhất định bao gồm tối ưu hóa

#include <stdio.h>  

void optimization_headache()  
{  
    int t = 11;  
    int l[1047] = {0};  
    int u_lu[23] = {0};  

    int u = 0;  

    l[0] = 0;  
    l[1] = 0;  

    do {  
     u++;  
     //printf("Incrementing u, now u is %d\n", u);  
     u_lu[u + 1] = u - l[u + 1];  
    } while ((u < t * 2) && (l[u + 1] <= t));  

    printf("u = %d, l[u] = %d, t = %d, u_lu[u] = %d\n", u, l[u], t, u_lu[u]);  
}  

int main()  
{  
    optimization_headache();  

    return 0;  
} 

Sau khi biên dịch với tối ưu hóa off ($ gcc -Wall -Wextra -O0 main.c), mã biên dịch, và tôi nhận được kết quả như sau:

u = 22, l[u] = 0, t = 11, u_lu[u] = 21

Khi tôi biên dịch với tối ưu hóa đầy đủ ($ gcc -Wall -Wextra -O3 main.c), chương trình bị treo và đầu cho biết nó đang sử dụng 100% CPU của tôi. Nó phải chạy mãi mãi trong vòng lặp while.

Tôi có thể lấy mã để biên dịch với tối ưu hóa đầy đủ và chạy một cách chính xác bằng cách thay đổi một hoặc tất cả các nội dung sau:

1) Nếu tôi nhận xét ra l[0] = 0; l[1] = 0;.

2) Nếu tôi thực hiện u a volatile int thay thế.

3) Nếu tôi bỏ ghi chú printf bên trong vòng lặp while.

Vì vậy, rõ ràng, tôi không hiểu những gì tối ưu hóa đang làm và tại sao nó thay đổi hành vi của chương trình của tôi. Tôi chỉ có thể chọn một trong những giải pháp trên để có được nó chạy, nhưng tôi thực sự thực sự muốn biết những gì đang xảy ra ở đây. Thật kỳ lạ với tôi.

(C++ thẻ có thể không thích hợp, nhưng tôi thấy hành vi tương tự sử dụng g ++ cũng)

+3

Hành vi biến mất với '-fno-hung-loop-optimizations' có nghĩa là bạn có thể có hành vi không xác định, xem [Lỗi biên dịch C++?] (Http://stackoverflow.com/q/32506643/1708801) để biết chi tiết giải thích về những gì gcc đang làm. Nhiều khả năng một truy cập vượt giới hạn đang xảy ra. –

+7

Mã của bạn có thể ghi vào 'u_lu [23]'. (bạn lặp trong khi 'u <22' nhưng' u' được tăng lên hai lần). – wimh

+0

Phiên bản gcc nào và bạn đang sử dụng nền tảng nào? Cả hai phiên bản biên dịch chỉ chạy tốt trên máy Mac của tôi. –

Trả lời

7

Như đã chỉ ra trong các ý kiến, điều này có thể xảy ra nếu bạn gọi undefined behavior.

Trong trường hợp của bạn, đây là phần có liên quan:

int t = 11;  
int u_lu[23] = {0};  

do {  
    u++;  
    u_lu[u + 1] = u - l[u + 1];  
} while ((u < t * 2) /*...*/);  

Các vòng lặp chạy trong khi u nhỏ sau đó 22, vì vậy nó có thể trở thành 21. Nhưng bên trong vòng lặp, bạn tăng u hai lần và bằng văn bản cho u_lu[23] . Đây là một cái nữa rồi được phân bổ.

Các vấn đề liên quan