2013-07-02 28 views
9

Tôi đã cố gắng gỡ lỗi lỗi phân đoạn gần đây bằng cách sử dụng valgrind trên mâm xôi Pi (mô hình b), chạy Debian GNU/Linux7.0 (wheezy). Mỗi lần tôi chạy valgrind trên một chương trình biên dịch C++, tôi nhận được một cái gì đó như sau:valgrind trả về hướng dẫn không được xử lý trên Raspberry Pi

disInstr(arm): unhandled instruction: 0xF1010200 
    cond=15(0xF) 27:20=16(0x10) 4:4=0 3:0=0(0x0) 
valgrind: Unrecognized instruction at address 0x4843638. 
at 0x4843638: ??? (in /usr/lib/arm-linux-gnueabihf/libconfi_rpi.so) 

Sau đó, những thứ valgrind bình thường, gây ra một SIGILL và chấm dứt chương trình của tôi. Lúc đầu, tôi giả định có một số rò rỉ bộ nhớ trong chương trình của tôi đã khiến nó thực thi một phần bộ nhớ không chỉ dẫn như một lệnh, nhưng sau đó tôi chạy mã hello world sau đây, và nhận được kết quả tương tự.

#include <iostream> 
using namespace std; 

int main() { 
cout<<"Hello World"<<endl; 

return 0; 
} 

Có thể không có khả năng rò rỉ bộ nhớ/segfault trong đó, vậy tại sao nó cho tôi lỗi này? Tôi khá mới với valgrind, nhưng tôi chạy nó với cơ bản nhất valgrind ./a.out.

+0

thử cách này: 'valgrind --tool = memcheck --leak-check = yes --show-reachable = yes --num-callers = 20 --track-fds = yes./A' và đăng những gì xảy ra. –

+0

tại sao bạn không sử dụng gdb debugger gdb? Nó rất dễ dàng để biết nguyên nhân của một segfault với nó! – Phong

+0

@Phong: Nó không phải là segfault. Valgrind không chắc chắn cách xử lý lệnh. – Cornstalks

Trả lời

7

Từ mã của bạn (một thế giới hello đơn giản), Nó khiếu nại về một số Unrecognized instruction at address 0x4843638. Đoán của tôi là:

  • Vì valgrind cần phải chặn chức năng gọi hệ thống malloc của bạn (thư viện chuẩn c). Điều này cho phép valgrind kiểm tra số lượng tài nguyên bạn đã cấp/miễn phí được sử dụng để phát hiện rò rỉ bộ nhớ (ví dụ). Nếu valgrind không nhận ra môi trường thư viện chuẩn của bạn (hoặc ngôn ngữ hướng dẫn của bộ xử lý của bạn), nó có thể không hoạt động như mong đợi, đó sẽ là nguyên nhân gây ra sự cố của bạn. Bạn nên kiểm tra phiên bản valgrind và tải xuống phiên bản được trang bị cho nền tảng của bạn.

EDIT:

http://valgrind.org/docs/manual/faq.html

3,3. chương trình của tôi chết, in một thông điệp như thế này trên đường đi:

làm phật ý x86-> IR: hướng dẫn byte unhandled: 0x66 0xF 0x2E 0x5

Một khả năng là chương trình của bạn có lỗi và sai lầm nhảy để một địa chỉ không mã, trong trường hợp đó bạn sẽ nhận được tín hiệu SIGILL. Memcheck có thể đưa ra một cảnh báo ngay trước khi điều này xảy ra, nhưng nó có thể không nếu bước nhảy xảy ra với bộ nhớ địa chỉ.

Một khả năng khác là Valgrind không xử lý lệnh. Nếu bạn đang sử dụng Valgrind cũ hơn, phiên bản mới hơn có thể xử lý lệnh . Tuy nhiên, tất cả các bộ hướng dẫn có một số hướng dẫn sử dụng ít được biết đến, hiếm khi là . Ngoài ra, trên amd64 có một số gần như vô hạn kết hợp các tiền tố hướng dẫn dư thừa, nhiều trong số chúng không có giấy tờ nhưng được chấp nhận bởi CPU. Vì vậy, Valgrind sẽ vẫn có lỗi giải mã theo thời gian. Nếu điều này xảy ra, vui lòng gửi báo cáo lỗi .

EDIT2:

Từ wikipedia, CPU Raspberry Pi:

  • 700 MHz ARM1176JZF-S lõi (ARM11 gia đình, tập lệnh ARMv6) [3]

2.11. Các giới hạn

Trên ARM, về cơ bản toàn bộ bộ hướng dẫn ARMv7-A được hỗ trợ, ở cả chế độ ARM và ngón tay cái. ThumbEE và Jazelle không được hỗ trợ. NEON, VFPv3 và Hỗ trợ đa phương tiện ARMv6 khá hoàn chỉnh.

Chương trình/thư viện của bạn vừa tình cờ có một số hướng dẫn chưa được hỗ trợ.

+0

Thực ra những gì bạn muốn làm là kiểm tra bản phát hành mới nhất. Nếu không có, thì đây là lỗi valgrind. Điền vào một vấn đề và hy vọng nó sẽ được cố định càng sớm càng tốt. (Dự án Valgrind lớn, vì vậy nếu họ có thể tái sản xuất, không nên mất nhiều thời gian) – Phong

+0

"Tải xuống phiên bản được trang bị cho nền tảng của bạn": Tôi đã cài đặt 'apt-get', vì vậy nó được trang bị riêng cho Raspbian. Tôi sẽ thử phiên bản mới nhất. – Cornstalks

+0

Tôi chỉ kiểm tra tính tương thích của tập lệnh giữa Raspberry (ARMv6) và valgrind. Và nó xuất hiện từ faq mà ARMv6 không hoàn toàn được hỗ trợ bởi valgrind. (Tôi đã cập nhật câu trả lời theo nó). Xin lỗi để thông báo muộn này. Tôi e rằng bạn không thể sử dụng vali trên vali của mình ... – Phong

3

TL; DR: xóa gói raspi-copies-and-fills nếu bạn đang sử dụng Raspbian. Nó cũng có thể hoạt động trong một số biến thể Linux khác như NOOBS.


Như Phong đã lưu ý, hướng dẫn này không được hỗ trợ bởi Valgrind. Có một bug report điều này giải thích vấn đề này:

này giữ xén lên, ví dụ gần đây nhất là tại lỗi 366464. Có lẽ tôi nên giải thích thêm tại sao điều này không được hỗ trợ. Đó là vì chúng tôi không có cách khả thi để thực hiện điều đó. Các công cụ JIT của Valgrind mã số khối khi chúng được truy cập lần đầu tiên và độ chính xác của các khối hiện tại được "nướng" vào thiết bị. Vì vậy, có hai lựa chọn:

(1) khi một hướng dẫn SETEND được thực thi, vứt bỏ tất cả các mã JITted rằng Valgrind đã tạo ra, và JIT khối mã mới với endianness mới.

(2) khối mã JIT một cách endian-agnostic và có một bài kiểm tra thời gian chạy cho mỗi truy cập bộ nhớ, để quyết định về việc có nên gọi một
endian chức năng đo đạc helper lớn hay nhỏ.

(1) mang lại hiệu suất bằng không cho mã không sử dụng SETEND nhưng một lần truy cập khổng lồ (hoàn toàn không khả thi) đối với mã thực hiện.

(2) thực hiện các thay đổi cuối cùng miễn phí, nhưng sẽ phạt tất cả lưu lượng bộ nhớ bất kể SETEND có thực sự được sử dụng hay không.

Vì vậy, tôi không tìm thấy một trong những điều đó có thể chấp nhận được.Và tôi không thể nghĩ ra bất kỳ cách nào khác để triển khai nó .

Nói cách khác, thật khó để thực hiện hướng dẫn này trong valgrind. Tóm tắt chủ đề: nguyên nhân phổ biến nhất của hướng dẫn này là một số chức năng quản lý bộ nhớ nhanh hơn mà tàu Raspberry Pi (memcmp, memset, v.v.).

Tôi đã giải quyết nó bằng cách (tạm thời) xóa raspi-copies-and-fills khỏi cài đặt Raspbian của tôi.

5

On Raspberry Pi 3 với noobs cài đặt của Raspian, thực hiện câu trả lời ayke bằng cách làm như sau trong một cửa sổ terminal:

  1. cd/etc
  2. sudo nano ld.so.preload
  3. Tháo dòng đó bao gồm "libarmmem.so" (/usr/lib/arm-linux-gnueabihf/libarmmem.so)
  4. Lưu và thoát ld.so.preload
  5. Run valgrind
  6. Đặt dòng trở lại vào ld.so.preload sau khi thử nghiệm valgrind hoàn tất

Các nạp sẵn "libarmmem.so" chứa các hướng dẫn "setend" trong chức năng "memcmp" mà gây ra lỗi hướng dẫn unhandled. Thư viện chuẩn (được sử dụng khi thư viện "libarmmem.so" được tải sẵn) không bao gồm lệnh "setend" trong "memcmp".

+0

giải pháp một dòng làm việc cho tôi và dễ dàng đảo ngược hơn: "sudo mv /etc/ld.so.preload /etc/ld.so.preload.disabled" –

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