2009-02-18 25 views
22

Tôi thấy rất khó để tìm ra những gì là sai với mã của tôi khi sử dụng C++ mẫu meta-lập trình. Có thể là tôi không hiểu rõ về thông báo lỗi, nhưng theo tôi biết, tôi không thể sử dụng các bản in hoặc điểm ngắt để tìm ra những gì đang diễn ra.Làm thế nào để bạn gỡ lỗi mã templated nặng trong c + +?

Bạn có thể cung cấp lời khuyên hoặc lời khuyên nào khi cố gắng tìm ra lý do tại sao thứ gì đó không biên dịch ngoài việc chỉ chọn mã thủ công và hy vọng nó sẽ đến với tôi?

Trả lời

14

Đối với STL, ít nhất cũng có các công cụ sẵn có sẽ tạo ra nhiều thông báo lỗi thân thiện với con người hơn. Xem http://www.bdsoft.com/tools/stlfilt.html

Đối với các mẫu không phải STL, bạn sẽ chỉ phải tìm hiểu ý nghĩa của các lỗi đó. Sau khi bạn đã nhìn thấy chúng một chục lần nó trở nên dễ dàng hơn để đoán những gì vấn đề là. Nếu bạn đăng chúng ở đây có lẽ ai đó có thể giúp bạn tìm ra.

7

Bạn có thể thử sử dụng trình biên dịch mới hơn. Nếu bạn đang sử dụng Visual C++ 6.0, chuyển sang 9.0 và bạn sẽ thấy một bước nhảy lớn trong tính hữu dụng của các lỗi trình biên dịch.

Nếu không, kỹ thuật của tôi thường được thử nghiệm dưới dạng một đoạn mã nhỏ nhất có thể cho đến khi tôi bị lỗi. Đây có lẽ là lỗi lớn nhất của hệ thống mẫu - không có cách nào để gỡ lỗi chúng.

Trong mã của riêng bạn, hãy sử dụng tự do compile-time asserts để giúp các vấn đề về sử dụng dễ chẩn đoán hơn một chút.

+0

Bạn có thể sử dụng xác nhận thời gian biên dịch mà không cần tăng cường. Chi tiết tại đây: http://www.pixelbeat.org/programming/gcc/static_assert.html – pixelbeat

+0

Trong môi trường công ty, bạn có thể không di chuyển ra khỏi VC6. –

+3

graham: Một công ty vẫn buộc các nhân viên của mình sử dụng VC6 là một công ty mà tôi không muốn làm việc cho, chưa bao giờ, trong mọi trường hợp. Cung cấp cho bạn những công cụ không phù hợp như vậy cho thấy rất rõ ràng rằng công ty không quan tâm đến bạn. Không phải là một mối quan hệ lành mạnh. –

3

Điều này sẽ giúp bạn tôi nghĩ.

http://www.bdsoft.com/tools/stlfilt.html

Tôi chưa tự sử dụng; nhưng, nó có thể giúp bạn. Tôi cũng có thể cho bạn biết rằng khi bạn có nhiều kinh nghiệm hơn với các mẫu và metaprogram, bạn sẽ quen với các thông báo lỗi. Đôi khi chúng có thể hơi khó đọc; nhưng, có logic cho sự điên rồ của họ. Chỉ cần làm cho thiết bị đầu cuối của bạn lớn như bạn có thể và cố gắng dịch những gì nó đang nói trong đầu của bạn khi bạn đọc nó.

3

Trình biên dịch bạn đang sử dụng? VC8 và 9 thực sự khá tốt khi xuất ra các thông báo lỗi có thể đọc được. Nó vẫn mất một chút kiên nhẫn để đi qua, nhưng nó có thể được thực hiện, và về cơ bản họ cho thấy tương đương thời gian biên dịch của ngăn xếp cuộc gọi. Bắt đầu từ phía dưới, mẫu instantiation nào gây ra lỗi và các đối số mẫu là gì? Cấp độ tiếp theo cho thấy mẫu nó được khởi tạo từ và tiếp tục, tất cả các con đường lên đến cấp cao nhất. Tất nhiên điều này chỉ hiển thị trong tab "đầu ra", không phải là "lỗi" mà nó thường hiển thị sau khi biên dịch không thành công.

Nguyên tắc tương tự trong GCC, mặc dù cuối cùng tôi đã thử, ít nhất, định dạng có phần ít đọc được hơn. Nhưng thực sự, bạn chỉ cần phải theo dõi qua các chồng của instantiations, và ở mỗi cấp, xác minh rằng nó đã instantiated với các loại bạn mong đợi, cho đến khi bạn tìm thấy một trong đó giới thiệu các lỗi.

Đó là một nỗi đau, nhưng nó có thể được thực hiện, và nó đòi hỏi không có gì nhiều hơn là kiên nhẫn và sẵn sàng để đọc các thông báo lỗi. :)

Ngoài ra, việc sử dụng tự do của static_assert (hoặc BOOST_STATIC_ASSERT) có thể giúp rất nhiều bằng cách cung cấp sự tỉnh táo kiểm tra

2

Bạn làm quen với nó khi thời gian trôi qua, và tiếc là nếu bạn có kế hoạch sử dụng C++, bạn phải . Bởi vì, một số thư viện như VC9 có thông báo lỗi tốt, nhưng ngay khi bạn chuyển sang nói GCC, hoặc một số trình biên dịch khác, các thư đã biến mất.Và ngay cả VC9 sẽ không giúp bạn nhiều khi bạn có lỗi từ một số thư viện được viết bởi người khác, hoặc bản thân bạn trong một đêm khuya, thậm chí một số thư viện Boost không thân thiện. Đơn giản bởi vì không phải mọi tác giả đều đưa ra những rắc rối để làm cho mọi thứ rõ ràng khi có lỗi xảy ra và thậm chí còn phổ biến hơn với các thư viện mới (có xu hướng có nhiều lỗi nhất và ít trợ giúp hơn). Ngoài ra bạn phải nhớ rằng STATIC_ERRORS đẹp bạn có thể tìm thấy ở đây và ở đó trong mã, được đặt bởi các tác giả, nơi mọi thứ thường phá vỡ, và sẽ luôn có trường hợp góc khủng khiếp, mà tác giả đã không chiêm ngưỡng, điều đó sẽ tạo ra 400 dòng thông báo lỗi vì bạn đã bỏ lỡ một nơi nào đó chẳng hạn.

Sử dụng các công cụ sẽ giúp bạn ngay từ đầu, nhưng làm tổn thương bạn về lâu dài. Và kể từ khi vấn đề là cố hữu của C + +, nó không phải đi xa bất kỳ ngày nào. Và những bức tường lỗi này có thể sẽ xảy ra với chúng tôi cho đến khi C++ không còn được sử dụng nữa. Vì vậy, các công cụ sẽ chỉ cắt răng của bạn, khi bạn cần chúng để tồn tại. Nếu bạn có kế hoạch rời khỏi C++ sớm thì vui lòng sử dụng chúng. Ngày nay tôi thường có thể hiểu được những thông báo lỗi 400 dòng trong nháy mắt, vì vậy chúng rõ ràng trong mắt tôi, nhưng đó không phải nhờ vào bất kỳ công cụ nào.

Như với mọi thứ, đặc biệt là C++, nó có kinh nghiệm và đào tạo.

5

Nếu bạn đang sử dụng gcc, tôi thấy rằng colorgcc có thể giúp bạn một chút. Mã hóa màu giúp phân tích các cảnh báo so với lỗi và thông tin theo ngữ cảnh dễ dàng hơn.

4

Khi thực hiện điều gì đó phức tạp trong ngôn ngữ lập trình meta, tôi sử dụng macro BOOST_MPL_ASSERT nhiều lần, kiểm tra kết quả của mỗi bước của siêu thực thi. Thư viện Boost.MPL rất hữu ích cho vấn đề đó. Tôi khuyên bạn nên sử dụng càng nhiều mã càng tốt, vì có khả năng nó sẽ không chứa lỗi.

Khi tôi không chắc chắn chuyên môn đúng cho một lớp đang được sử dụng, tôi có xu hướng cô lập chuyên môn đúng trong không gian tên. Một khi bạn chắc chắn rằng chuyên môn là hợp lệ, bạn phải chắc chắn rằng nó được chọn. Nếu không, bạn phải tìm ra cái nào được chọn ở vị trí của nó. Sau đó, tôi khuyên bạn nên sử dụng Boost.EnableIf để loại trừ chuyên môn được chấp nhận sai này khỏi quá trình lựa chọn.

Cuối cùng nhưng không kém phần quan trọng, STLfilt cực kỳ hữu ích và bạn có thể tự sửa đổi nó để phù hợp với nhu cầu của bạn càng tốt.

Nhưng điều quan trọng nhất là cố gắng không sử dụng lập trình meta ở mọi nơi. Nó phức tạp, vì vậy hãy sử dụng nó chỉ khi bạn thực sự cần.

2

Như câu trả lời đã minh họa, về cơ bản có 2 loại khó khăn trong mẫu mã: 1. nhận được nó để biên dịch, và tìm ra nguyên nhân cho các lỗi biên dịch 2. nhận nó làm làm điều đúng trong thời gian chạy

Tôi thường cố gắng tách biệt loại ma thuật thời gian biên dịch khỏi logic thời gian chạy, điều này giúp tìm ra nguyên nhân của sự cố (Loại 1 hoặc 2). Cách để đạt được điều này là sử dụng một loại mẫu cho phép loại, và ít nhất là chức năng thời gian chạy có thể, và một kiểu đơn giản cho logic thời gian chạy, sử dụng kiểu mẫu.

Nếu sau đó bạn làm theo lời khuyên từ các thư trả lời khác, đặc biệt là câu trả lời về xác nhận compile_time, sẽ dễ dàng tìm ra nguồn gốc của sự cố.

0

Metashell là một công cụ tuyệt vời cho mẫu gỡ lỗi. Với chế độ trực tuyến!

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