2011-11-28 28 views
10

Kiến thức của tôi về bộ chỉ dẫn intel là một chút gỉ. Bạn có thể cho tôi biết lý do tại sao tôi có thể bị lỗi phân đoạn trong phiên bản tối ưu hóa chức năng của tôi (điểm thưởng nếu bạn có thể cho tôi biết tại sao tôi không nhận được nó trong bản dựng mã -O0. biên soạn bởi GCC 4.1.2SIGSEGV trong phiên bản tối ưu của mã

Dưới đây là kết quả của "disas" lệnh GDB tại vụ tai nạn:.

0x00000000004263e5 <+0>:  sub $0x8,%rsp 
    0x00000000004263e9 <+4>:  movsd %xmm2,(%rsp) 
    0x00000000004263ee <+9>:  divsd %xmm1,%xmm0 
    0x00000000004263f2 <+13>: callq 0x60f098 <[email protected]> 
=> 0x00000000004263f7 <+18>: andpd 0x169529(%rip),%xmm0   
    0x00000000004263ff <+26>: movsd (%rsp),%xmm1 
    0x0000000000426404 <+31>: ucomisd %xmm0,%xmm1 
    0x0000000000426408 <+35>: seta %al 
    0x000000000042640b <+38>: movzbl %al,%eax 
    0x000000000042640e <+41>: add $0x8,%rsp 
    0x0000000000426412 <+45>: retq 

Và đây là nguồn gốc của hàm:

char is_within_range(double a, double b, double range) { 
    double ratio = a/b; 
    double logRatio = fabs(log(ratio)); 
    return logRatio < range; 
} 

Để tham khảo đây là phiên bản không được tối ưu hóa của mã:

0x00000000004263e5 <+0>: push %rbp 
    0x00000000004263e6 <+1>: mov %rsp,%rbp 
    0x00000000004263e9 <+4>: sub $0x30,%rsp 
    0x00000000004263ed <+8>: movsd %xmm0,-0x18(%rbp) 
    0x00000000004263f2 <+13>: movsd %xmm1,-0x20(%rbp) 
    0x00000000004263f7 <+18>: movsd %xmm2,-0x28(%rbp) 
    0x00000000004263fc <+23>: movsd -0x18(%rbp),%xmm0 
    0x0000000000426401 <+28>: divsd -0x20(%rbp),%xmm0 
    0x0000000000426406 <+33>: movsd %xmm0,-0x10(%rbp) 
    0x000000000042640b <+38>: mov -0x10(%rbp),%rax 
    0x000000000042640f <+42>: mov %rax,-0x30(%rbp) 
    0x0000000000426413 <+46>: movsd -0x30(%rbp),%xmm0 
    0x0000000000426418 <+51>: callq 0x610608 <[email protected]> 
    0x000000000042641d <+56>: movapd %xmm0,%xmm1 
    0x0000000000426421 <+60>: movsd 0x16b6b7(%rip),%xmm0 
    0x0000000000426429 <+68>: andpd %xmm1,%xmm0 
    0x000000000042642d <+72>: movsd %xmm0,-0x8(%rbp) 
    0x0000000000426432 <+77>: movsd -0x8(%rbp),%xmm1 
    0x0000000000426437 <+82>: movsd -0x28(%rbp),%xmm0 
    0x000000000042643c <+87>: ucomisd %xmm1,%xmm0 
    0x0000000000426440 <+91>: seta %al 
    0x0000000000426443 <+94>: movzbl %al,%eax 
    0x0000000000426446 <+97>: leaveq 
    0x0000000000426447 <+98>: retq 
+1

Bạn đã kiểm tra sự khác biệt với mã không được tối ưu hóa (đầu ra lắp ráp) chưa?Nếu có, bạn có thể đăng nó không? – Macmade

+0

Đầu vào có quan trọng không? – sehe

+0

Tôi không nghĩ rằng đầu vào thực sự quan trọng ... – Macmade

Trả lời

6
=> 0x00000000004263f7 <+18>: andpd 0x169529(%rip),%xmm0   
    0x00000000004263ff <+26>: movsd (%rsp),%xmm1 

Khi hướng dẫn andpd mất một toán hạng bộ nhớ, nó cần phải được liên kết đến một ranh giới 16-byte.

Để %rip địa chỉ liên quan, chênh lệch được áp dụng cho địa chỉ của hướng dẫn sau đây. Vì vậy, ở đây, toán hạng bộ nhớ là 0x4263ff + 0x169529 = 0x58f928, mà không phải là 16-byte phù hợp. Do đó segfault.

Trình biên dịch trực tiếp tạo mã cho fabs(), sử dụng AND và mặt nạ bit thích hợp để xóa bit dấu; giá trị hằng số bit mặt nạ nên được đặt ở mức bù thích hợp trong phần dữ liệu được căn chỉnh đủ, nhưng chưa được. Điều này có thể là một lỗi trong phiên bản cũ của GCC, hoặc có thể là một vấn đề liên quan đến mối liên kết ở một nơi khác.

+0

Theo dõi điều này, là câu trả lời của bạn là tại chỗ, nó hóa ra là một lỗi liên kết trong một liên kết không chuẩn mà chúng tôi đang sử dụng. Cảm ơn câu trả lời. – laslowh

1

Dường như sụp đổ sau khi cuộc gọi đến log chức năng:

callq 0x60f098 <[email protected]> 

Vì vậy, có lẽ là một vấn đề với việc thực hiện fabs, sử dụng -O0.

Các bạn đã thử:

double logRatio = log(ratio); 
logRatio = fabs(logRatio); 

Điều này có thể tạo ra một sản lượng lắp ráp khác nhau, và bạn có thể nhận được infos thêm về vụ tai nạn.

Là một thay thế, bạn có thể thay thế các fabs cuộc gọi với một cái gì đó như:

double logRatio = log(ratio); 
logRatio = (logRatio < 0) -logRatio : logRatio; 

Bạn có thể có những vấn đề chính xác với điều đó, nhưng đó không phải là điểm ở đây ...

1

Tôi cũng sử dụng gcc (GCC) 4.1.2 20070115 (SUSE Linux), đây là cụm được tạo:

Dump of assembler code for function is_within_range: 
0x0000000000400580 <is_within_range+0>: divsd %xmm1,%xmm0 
0x0000000000400584 <is_within_range+4>: sub $0x8,%rsp 
0x0000000000400588 <is_within_range+8>: movsd %xmm2,(%rsp) 
0x000000000040058d <is_within_range+13>:  callq 0x400498 <[email protected]> 
0x0000000000400592 <is_within_range+18>:  andpd 358(%rip),%xmm0  # 0x400700 
0x000000000040059a <is_within_range+26>:  xor %eax,%eax 
0x000000000040059c <is_within_range+28>:  movsd (%rsp),%xmm1 
0x00000000004005a1 <is_within_range+33>:  ucomisd %xmm0,%xmm1 
0x00000000004005a5 <is_within_range+37>:  seta %al 
0x00000000004005a8 <is_within_range+40>:  add $0x8,%rsp 
0x00000000004005ac <is_within_range+44>:  retq 

Dường như gần như giống nhau, nhưng tôi không gặp sự cố. Tôi nghĩ bạn sẽ cần cung cấp cho chúng tôi cờ biên dịch và thông tin chi tiết về bộ xử lý và phiên bản GLIBC của bạn và các giá trị a, brange gây sự cố cho bạn vì sự cố gần như chắc chắn với cuộc gọi log.

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