Pertanyaan Alat untuk menghasilkan pesan kesalahan berkualitas lebih tinggi untuk kode berbasis template?


Konsep, yang akan membuat alat-alat ini tidak perlu, adalah bukan bagian dari C ++ 11.

  • STLFilt akan menjadi salah satu pilihan tetapi tidak lagi dipertahankan.

  • Dentang klaim untuk memberikan diagnosa ekspresif meskipun penting C ++ 11 fitur belum tersedia.

  • colorgcc tampaknya ditinggalkan sejak 1999.

Alat kualitas produksi apa yang tersedia untuk memecahkan pesan kesalahan yang berasal dari kode berbasis template? Dukungan Eclipse-CDT akan menyenangkan juga. :)

Jika saya menyerah pada C ++ 11, opsi apa yang saya miliki untuk C ++ 98?


Pertanyaan-pertanyaan Terkait:


32
2018-01-08 17:18


asal


Jawaban:


Mari kita tusuk jawaban (saya menandai komunitas ini sehingga kami mendapat tanggapan yang baik bersama-sama) ...

Saya bekerja sejak lama dengan template dan pesan kesalahan umumnya telah diperbaiki dalam beberapa cara:

  • Menulis setumpuk kesalahan menciptakan lebih banyak teks tetapi juga biasanya mencakup tingkat yang dilihat pengguna dan ini biasanya mencakup petunjuk tentang apa masalah sebenarnya. Mengingat bahwa kompiler hanya melihat unit terjemahan dilemparkan padanya, tidak banyak yang dapat dilakukan untuk menentukan kesalahan dalam tumpukan yang paling cocok untuk pengguna.
  • Menggunakan pemeriksa konsep, yaitu kelas atau fungsi yang melatih semua anggota yang diperlukan dari argumen template dan mungkin menghasilkan pesan kesalahan menggunakan static_assert() beri penulis template cara untuk memberi tahu pengguna tentang asumsi yang tampaknya tidak berlaku.
  • Memberi tahu pengguna tentang jenis yang dia tulis alih-alih memperluas semua typedef karena kompiler suka melihat pada level terendah juga membantu. clang cukup bagus dalam hal ini dan benar-benar memberi Anda pesan kesalahan mis. membicarakan tentang std::string daripada memperluas hal-hal menjadi apa pun akhirnya.

Kombinasi teknik sebenarnya yang menyebabkan misalnya clang untuk membuat pesan kesalahan yang cukup baik (bahkan jika itu tidak menerapkan C ++ 2011, namun; tidak ada kompiler dan sejauh yang saya tahu gcc dan clang memimpin paket). Saya tahu pengembang kompiler lainnya secara aktif bekerja untuk memperbaiki pesan kesalahan template karena banyak programmer telah menemukan bahwa template sebenarnya adalah lompatan besar ke depan meskipun pesan kesalahan adalah sesuatu yang perlu sedikit membiasakan diri.

Salah satu alat masalah seperti wajah stlfilt adalah bahwa C ++ compiler dan pustaka sedang dalam pengembangan aktif. Ini menghasilkan pesan kesalahan bergeser sepanjang waktu, menyebabkan alat untuk menerima output yang berbeda. Meskipun baik bahwa para penulis kompilator bekerja untuk memperbaiki pesan kesalahan, ini tentu membuat hidup lebih sulit bagi orang yang mencoba bekerja dari pesan kesalahan yang mereka dapatkan. Ada sisi lain untuk ini juga: sekali pola kesalahan tertentu terdeteksi menjadi umum dan dijemput misalnya. oleh stlfilt (well, itu tidak aktif dipertahankan sejauh yang saya tahu) penulis kompiler mungkin ingin melaporkan kesalahan mengikuti pola-pola ini secara langsung, mungkin juga menyediakan informasi tambahan yang tersedia untuk compiler tetapi tidak dipancarkan sebelumnya. Dengan kata lain, saya berharap bahwa penulis kompilator cukup menerima laporan dari pengguna yang menggambarkan situasi kesalahan umum dan bagaimana mereka dilaporkan terbaik. Penulis kompiler mungkin tidak menemukan kesalahan itu sendiri karena kode yang mereka kerjakan sebenarnya adalah C (misalnya gcc diimplementasikan dalam C) atau karena mereka begitu terbiasa dengan teknik template tertentu sehingga mereka menghindari kesalahan tertentu (misalnya kelalaian typenameuntuk jenis dependen).

Akhirnya, untuk menjawab pertanyaan tentang alat-alat konkrit: "alat" utama yang saya gunakan ketika saya terjebak dengan kompilator yang mengeluh tentang beberapa instantiasi template adalah dengan menggunakan kompiler yang berbeda! Meskipun tidak selalu terjadi tetapi sering kali satu kompilator melaporkan pesan kesalahan yang sepenuhnya tidak dapat dimengerti yang hanya masuk akal setelah melihat laporan yang cukup singkat dari kompilator lain (jika Anda tertarik, saya secara teratur menggunakan gcc, clang, dan EDG versi terbaru untuk ini). Saya juga tidak tahu paket yang siap pakai seperti stlfilt.


16
2018-01-15 12:01



Saya tahu ini mungkin tidak membantu seperti yang Anda inginkan, tetapi saya telah menemukan alat terbaik terhadap pesan kesalahan template pengetahuan.

Pemahaman yang baik tentang STL dan cara menggunakannya akan membantu Anda menghindari banyak kesalahan di tempat pertama. Kedua, sering pesan kesalahan merujuk ke fungsi dalam sumber STL - jika Anda memiliki gambaran kasar bagaimana STL diimplementasikan, ini bisa sangat membantu dalam mengartikan apa yang terjadi pada pesan kesalahan. Akhirnya, pembuat compiler menyadari masalah ini dan secara bertahap meningkatkan output pesan kesalahan, sehingga Anda sebaiknya tetap menggunakan versi terbaru dari kompilator Anda.

Berikut contoh kesalahan templat yang tidak jelas:

std::vector<std::unique_ptr<int>> foo;
std::vector<std::unique_ptr<int>> bar = foo;

unique_ptr tidak bisa ditiru, itu hanya bisa dipindahkan. Jadi, mencoba menetapkan vektor unique_ptr ke vektor lain berarti di suatu tempat di kode sumber vektor akan mencoba menyalin penunjuk unik. Oleh karena itu kesalahan akan berasal dari kode yang bukan milik Anda dan melemparkan pesan kesalahan yang cukup buram sebagai hasilnya. Pesan kesalahan yang ideal adalah

main.cpp (20): tidak dapat membangun 'bar' dari 'foo': jenis template foo tidak dapat diproksikan

Sebaliknya, VS2010 memberikan kesalahan berikut:

1>C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\xmemory(48): error C2248: 'std::unique_ptr<_Ty>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<_Ty>'
1>          with
1>          [
1>              _Ty=int
1>          ]
1>          C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\memory(2347) : see declaration of 'std::unique_ptr<_Ty>::unique_ptr'
1>          with
1>          [
1>              _Ty=int
1>          ]
1>          C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\xmemory(197) : see reference to function template instantiation 'void std::_Construct<std::unique_ptr<_Ty>,const std::unique_ptr<_Ty>&>(_Ty1 *,_Ty2)' being compiled
1>          with
1>          [
1>              _Ty=int,
1>              _Ty1=std::unique_ptr<int>,
1>              _Ty2=const std::unique_ptr<int> &
1>          ]
1>          C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\xmemory(196) : while compiling class template member function 'void std::allocator<_Ty>::construct(std::unique_ptr<int> *,const _Ty &)'
1>          with
1>          [
1>              _Ty=std::unique_ptr<int>
1>          ]
1>          C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\vector(421) : see reference to class template instantiation 'std::allocator<_Ty>' being compiled
1>          with
1>          [
1>              _Ty=std::unique_ptr<int>
1>          ]
1>          C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\vector(481) : see reference to class template instantiation 'std::_Vector_val<_Ty,_Alloc>' being compiled
1>          with
1>          [
1>              _Ty=std::unique_ptr<int>,
1>              _Alloc=std::allocator<std::unique_ptr<int>>
1>          ]
1>         main.cpp(19) : see reference to class template instantiation 'std::vector<_Ty>' being compiled
1>          with
1>          [
1>              _Ty=std::unique_ptr<int>
1>          ]

Memilah-milah ini ada petunjuk. Bagian pertama referensi akses anggota pribadi std::unique_ptr<int>. Bagian kedua, jika Anda mengklik ke baris sumber, menunjuk pada salinan konstruktor unique_ptr, yang dideklarasikan di bawah private: penentu. Jadi sekarang kami tahu kami mencoba menyalin unique_ptr yang tidak diizinkan. Bagian 3, 4, dan 5 hanya mengarah ke kode boilerplate - itu hanya suara. Bagian 6 mengatakan "lihat referensi ke instantiasi template kelas 'std :: _ Vector_val <_Ty, _Alloc>' sedang dikompilasi". Dengan kata lain, kesalahan ini terjadi dalam kode template vektor. Bagian terakhir yang paling menarik: langsung menunjuk pada garis yang menyatakan foo dalam kode sumber Anda sendiri - itu menemukan di mana di kode sumber Anda kesalahan berasal dari!

Jadi, tambahkan petunjuk:

  • Itu berasal dari foo,
  • Ini berasal dari kode vektor,
  • Ini mencoba menyalin unique_ptr yang tidak diizinkan.
  • Kesimpulan: vektor mencoba menyalin salah satu elemennya, yang tidak diizinkan. Tinjau kode untuk foo dan periksa apa pun yang menyebabkan salinan.

Karena compiler hanya menunjuk pada deklarasi foo, jika penugasannya jauh dalam kode sumber, maka perburuan akan dilibatkan. Ini jelas tidak ideal, tetapi saya pikir pendekatan ini pada akhirnya memberi Anda lebih banyak kesempatan untuk memperbaiki kesalahan secara umum. Anda akan mulai mengenali bahwa jenis kesalahan dump berarti "Anda menyalin unique_ptr". Sekali lagi, saya tidak membelanya, itu pasti perlu ditingkatkan - tapi saya pikir hari-hari ini ada hanya informasi yang cukup dalam output yang dikombinasikan dengan pengetahuan yang baik tentang STL memungkinkan Anda untuk memperbaiki masalah.


9
2018-01-16 00:28



Saya telah menemukan Clang untuk menghasilkan pesan kesalahan terbaik untuk kode templated berat. Tentu saja verbositas tidak dapat dihindari dalam banyak kasus, tetapi masih lebih baik daripada GCC atau MSVC sebagian besar waktu. Inilah pesan galat Clang untuk kode contoh yang diposting oleh AshleysBrain:

$ clang++ -std=c++11 -stdlib=libc++ -o dummy dummy.cpp 
In file included from dummy.cpp:1:
In file included from /usr/include/c++/v1/vector:243:
In file included from /usr/include/c++/v1/__bit_reference:15:
In file included from /usr/include/c++/v1/algorithm:594:
/usr/include/c++/v1/memory:1425:36: error: calling a private constructor of class 'std::__1::unique_ptr<int,
      std::__1::default_delete<int> >'
                ::new ((void*)__p) _Tp(_STD::forward<_Args>(__args)...);
                                   ^
/usr/include/c++/v1/memory:1358:14: note: in instantiation of function template specialization
      'std::__1::allocator_traits<std::__1::allocator<std::__1::unique_ptr<int, std::__1::default_delete<int> > >
      >::__construct<std::__1::unique_ptr<int, std::__1::default_delete<int> >, std::__1::unique_ptr<int,
      std::__1::default_delete<int> > &>' requested here
            {__construct(__has_construct<allocator_type, pointer, _Args...>(),
             ^
/usr/include/c++/v1/vector:781:25: note: in instantiation of function template specialization
      'std::__1::allocator_traits<std::__1::allocator<std::__1::unique_ptr<int, std::__1::default_delete<int> > >
      >::construct<std::__1::unique_ptr<int, std::__1::default_delete<int> >, std::__1::unique_ptr<int,
      std::__1::default_delete<int> > &>' requested here
        __alloc_traits::construct(__a, _STD::__to_raw_pointer(this->__end_), *__first);
                        ^
/usr/include/c++/v1/vector:924:9: note: in instantiation of function template specialization
      'std::__1::vector<std::__1::unique_ptr<int, std::__1::default_delete<int> >,
      std::__1::allocator<std::__1::unique_ptr<int, std::__1::default_delete<int> > >
      >::__construct_at_end<std::__1::unique_ptr<int, std::__1::default_delete<int> > *>' requested here
        __construct_at_end(__x.__begin_, __x.__end_);
        ^
dummy.cpp:7:37: note: in instantiation of member function 'std::__1::vector<std::__1::unique_ptr<int,
      std::__1::default_delete<int> >, std::__1::allocator<std::__1::unique_ptr<int, std::__1::default_delete<int> > >
      >::vector' requested here
        std::vector<unique_ptr<int>> bar = foo;
                                           ^
/usr/include/c++/v1/memory:1997:5: note: declared private here
    unique_ptr(const unique_ptr&);
    ^
1 error generated.

Ini masih panjang dan jelek, tapi menurut saya lebih jelas mengenai apa / di mana masalahnya.


4