

Perpustakaan Assersi C ++ yang paling terlalu direkayasa
Filsafat Perpustakaan: Berikan info diagnostik sebanyak mungkin yang bermanfaat.
Beberapa hal luar biasa yang dilakukan perpustakaan:
void zoog ( const std::map<std::string, int >& map) {
DEBUG_ASSERT (map. contains ( " foo " ), " expected key not found " , map);
}
ASSERT (vec.size() > min_items(), "vector doesn't have enough items", vec);
std::optional< float > get_param ();
float f = * ASSERT_VAL (get_param());
Jenis pernyataan:
Pernyataan Bersyarat:
DEBUG_ASSERT : Diperiksa dalam debug tetapi tetapi tidak melakukan apa pun dalam rilis (analog dengan assert perpustakaan standar)ASSERT : diperiksa dalam debug dan rilisASSUME : Diperiksa dalam debug dan berfungsi sebagai petunjuk optimasi dalam rilisPernyataan Tanpa Syarat:
PANIC : Pemicu dalam debug dan rilisUNREACHABLE : Pemicu dalam debug, ditandai sebagai tidak terjangkau dalam rilis Lebih suka assert lowecase?
Anda dapat mengaktifkan debug_assert huruf kecil dan assert alias dengan -DLIBASSERT_LOWERCASE .
Ringkasan fitur:
ASSERT_EQ dll.DEBUG_ASSERT_VAL dan ASSERT_VAL yang mengembalikan nilai sehingga mereka dapat diintegrasikan dengan mulus ke dalam kode, misalnya FILE* f = ASSERT_VAL(fopen(path, "r") != nullptr) include (FetchContent)
FetchContent_Declare(
libassert
GIT_REPOSITORY https://github.com/jeremy-rifkin/libassert.git
GIT_TAG v2.1.2 # <HASH or TAG>
)
FetchContent_MakeAvailable(libassert)
target_link_libraries (your_target libassert::assert)
# On windows copy libassert.dll to the same directory as the executable for your_target
if ( WIN32 )
add_custom_command (
TARGET your_target POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE:libassert::assert>
$<TARGET_FILE_DIR:your_target>
)
endif () Pastikan untuk mengonfigurasi dengan -DCMAKE_BUILD_TYPE=Debug atau -DDCMAKE_BUILD_TYPE=RelWithDebInfo untuk simbol dan informasi garis.
Pada macOS disarankan untuk menghasilkan file .dsym, lihat platform logistik di bawah ini.
Untuk cara lain menggunakan perpustakaan, seperti melalui manajer paket atau instalasi sistem di seluruh sistem, lihat penggunaan di bawah ini.
Pada dasarnya peran pernyataan adalah untuk memverifikasi asumsi yang dibuat dalam perangkat lunak dan mengidentifikasi pelanggaran yang dekat dengan sumber mereka. Perkecil pernyataan harus memprioritaskan memberikan informasi dan konteks sebanyak mungkin kepada pengembang untuk memungkinkan triase cepat. Sayangnya, bahasa dan alat perpustakaan yang ada memberikan informasi triase yang sangat terbatas.
Misalnya dengan pernyataan stdlib pernyataan seperti assert(n <= 12); Tidak memberikan informasi tentang kegagalan mengapa gagal atau apa yang menyebabkan kegagalannya. Memberikan jejak tumpukan dan nilai n Greatley meningkatkan triase dan debugging. Idealnya kegagalan pernyataan harus memberikan informasi diagnostik yang cukup bahwa pemrograman tidak harus menjalankan kembali dalam debugger untuk menentukan masalah.
Versi 1 dari perpustakaan ini adalah sebuah eksplorasi yang melihat seberapa banyak informasi dan fungsionalitas yang bermanfaat dapat dikemas dalam pernyataan sementara juga menyediakan antarmuka yang cepat dan mudah bagi pengembang.
Versi 2 dari perpustakaan ini mengambil pelajaran yang dipetik dari versi 1 untuk membuat alat yang secara pribadi saya temukan sangat diperlukan dalam pengembangan.
Fitur terpenting yang didukung perpustakaan ini adalah dekomposisi ekspresi otomatis. Tidak perlu untuk ASSERT_LT atau kerumitan lainnya, assert(vec.size() > 10); dipahami secara otomatis, seperti yang dipamerkan di atas.
Nilai yang terlibat dalam ekspresi menegaskan ditampilkan. Diagnostik redundan seperti 2 => 2 dihindari.
DEBUG_ASSERT (map.count( 1 ) == 2);
Hanya ekspresi tegas penuh yang dapat diekstraksi dari panggilan makro. Menunjukkan bagian mana dari ekspresi yang sesuai dengan nilai apa yang memerlukan beberapa penguraian ekspresi dasar. Tata bahasa C ++ bersifat ambigu tetapi sebagian besar ekspresi dapat disamban.
Semua pernyataan dalam perpustakaan ini mendukung pesan diagnostik opsional serta pesan diagnostik lainnya yang sewenang -wenang.
FILE* f = ASSERT_VAL(fopen(path, " r " ) != nullptr , " Internal error with foobars " , errno, path); Penanganan khusus disediakan untuk errno , dan Strerror dipanggil secara otomatis.
Catatan: Diagnostik tambahan hanya dievaluasi dalam jalur kegagalan suatu pernyataan.

Banyak pekerjaan telah dilakukan untuk menghasilkan jejak tumpukan yang cukup dan memformatnya sebaik mungkin. CPPTRACE digunakan sebagai solusi portabel dan mandiri untuk stacktraces pre-C ++ 23. Konfigurasi opsional dapat ditemukan dalam dokumentasi perpustakaan.
Salah satu fitur yang perlu dicatat adalah bahwa alih -alih selalu mencetak jalur lengkap, hanya jumlah minimum direktori yang diperlukan untuk membedakan jalur yang dicetak.

Fitur lain yang layak ditunjukkan adalah bahwa jejak tumpukan akan melipat jejak dengan rekursi yang dalam:

Penangan pernyataan menerapkan sintaks yang menyoroti di mana pun sesuai, seperti yang terlihat pada semua tangkapan layar di atas. Ini untuk membantu meningkatkan keterbacaan.
Libassert mendukung penangan kegagalan pernyataan khusus:
void handler (assert_type type, const assertion_info& assertion) {
throw std::runtime_error ( " Assertion failed: n " + assertion. to_string ());
}
int main () {
libassert::set_failure_handler (handler);
} Banyak perawatan diberikan untuk memproduksi stringifikasi nilai debug seefektif mungkin: string, karakter, angka, semuanya harus dicetak seperti yang Anda harapkan. Selain itu, wadah, tupel, std :: opsional, pointer pintar, dll. Semuanya terentang untuk menampilkan informasi sebanyak mungkin. Jika tipe yang ditentukan pengguna Overloads operator<<(std::ostream& o, const S& s) , kelebihan beban itu akan dipanggil. Kalau tidak, itu pesan default akan dicetak. Selain itu, titik kustomisasi stringifikasi disediakan:
template <> struct libassert ::stringifier<MyObject> {
std::string stringify ( const MyObject& type) {
return ...;
}
};

Nilai pernyataan dicetak dalam hex atau biner serta desimal jika hex/biner digunakan di kedua sisi ekspresi pernyataan:
ASSERT (get_mask() == 0b00001101);
Karena ekspresi sudah secara otomatis terurai, Anda dapat memilih untuk memiliki perbandingan yang tidak ditandatangani yang dilakukan secara otomatis dilakukan dengan keamanan tanda dengan -DLIBASSERT_SAFE_COMPARISONS :
ASSERT ( 18446744073709551606ULL == - 10 );
Libassert menyediakan dua header <libassert/assert-catch2.hpp> dan <libassert/assert-gtest.hpp> untuk digunakan dengan catch2 dan googletest.
Output contoh dari gtest:

Informasi lebih lanjut di bawah ini.
Libassert menyediakan tiga jenis pernyataan, masing -masing bervariasi sedikit tergantung pada kapan harus diperiksa dan bagaimana harus ditafsirkan:
| Nama | Memengaruhi |
|---|---|
DEBUG_ASSERT | Diperiksa di debug, tidak ada codegen dalam rilis |
ASSERT | Memeriksa baik debug dan rilis build |
ASSUME | Check -in debug, if(!(expr)) { __builtin_unreachable(); } dalam rilis |
Pernyataan tanpa syarat
| Nama | Memengaruhi |
|---|---|
PANIC | Memicu debug dan rilis |
UNREACHABLE | Dipicu dalam debug, ditandai sebagai tidak terjangkau dalam rilis. |
Satu manfaat untuk PANIC dan UNREACHABLE atas ASSERT(false, ...) adalah bahwa kompiler mendapatkan informasi [[noreturn]] .
ASSUME menandai jalur gagal sebagai rilis yang tidak terjangkau, berpotensi memberikan informasi yang bermanfaat kepada pengoptimal. Ini bukan perilaku default untuk semua pernyataan karena konsekuensi langsung dari ini adalah bahwa kegagalan pernyataan pada -DNDEBUG dapat menyebabkan UB dan lebih baik membuat ini sangat eksplisit.
Varian pernyataan yang dapat digunakan secara in-line dalam suatu ekspresi, seperti FILE* file = ASSERT_VAL(fopen(path, "r"), "Failed to open file"); , juga tersedia:
| Nama | Memengaruhi |
|---|---|
DEBUG_ASSERT_VAL | Diperiksa dalam debug, harus dievaluasi baik dalam debug dan rilis |
ASSERT_VAl | Memeriksa baik debug dan rilis build |
ASSUME_VAL | Check -in debug, if(!(expr)) { __builtin_unreachable(); } dalam rilis |
Catatan: Bahkan dalam rilis membangun ekspresi untuk DEBUG_ASSERT_VAL masih harus dievaluasi, tidak seperti DEBUG_ASSERT . Tentu saja, jika hasilnya tidak digunakan dan tidak menghasilkan efek samping itu akan dioptimalkan.
Kinerja: Sejauh kinerja runtime, dampak di Callites sangat minim di bawah -Og atau lebih tinggi. Jalur cepat dalam kode (yaitu, di mana pernyataan tidak gagal), akan cepat. Banyak pekerjaan yang diperlukan untuk memproses kegagalan pernyataan begitu terjadi. Namun, karena kegagalan harus jarang, ini seharusnya tidak masalah.
Kecepatan kompilasi : , ada biaya kompilasi-waktu yang terkait dengan semua instantiasi templat yang diperlukan untuk sihir perpustakaan ini.
Lainnya:
Catatan
Karena dekomposisi ekspresi, ASSERT(1 = 2); mengkompilasi.
Semua fungsi pernyataan adalah makro. Berikut adalah beberapa deklarasi semu untuk berinteraksi dengan mereka:
void DEBUG_ASSERT (expression, [optional message], [optional extra diagnostics, ...]);
void ASSERT (expression, [optional message], [optional extra diagnostics, ...]);
void ASSUME (expression, [optional message], [optional extra diagnostics, ...]);
decltype ( auto ) DEBUG_ASSERT_VAL(expression, [optional message], [optional extra diagnostics, ...]);
decltype ( auto ) ASSERT_VAL (expression, [optional message], [optional extra diagnostics, ...]);
decltype ( auto ) ASSUME_VAL (expression, [optional message], [optional extra diagnostics, ...]);
void PANIC ([optional message], [optional extra diagnostics, ...]);
void UNREACHABLE ([optional message], [optional extra diagnostics, ...]); -DLIBASSERT_PREFIX_ASSERTIONS dapat digunakan untuk mengawali makro ini dengan LIBASSERT_ . Ini berguna untuk membungkus pernyataan libassert.
-DLIBASSERT_LOWERCASE dapat digunakan untuk mengaktifkan debug_assert dan assert alias untuk DEBUG_ASSERT dan ASSERT . Lihat: Mengganti <Cassert>.
expression expression secara otomatis didekomposisi sehingga informasi diagnostik dapat disediakan. Jenis yang dihasilkan harus dapat dikonversi ke Boolean.
Operasi antara sisi kiri dan kanan operasi tingkat atas di pohon ekspresi dievaluasi oleh objek fungsi.
CATATAN: Operator logis Boolean ( && dan || ) tidak terurai secara default karena sirkuit pendek.
assertion message Pesan pernyataan opsional dapat disediakan. Jika argumen pertama yang mengikuti ekspresi pernyataan, atau argumen pertama dalam panik/tidak terjangkau, adalah jenis string apa pun yang akan digunakan sebagai pesan (jika Anda ingin parameter pertama, yang kebetulan merupakan string, menjadi nilai diagnostik tambahan sebagai gantinya lulus string kosong terlebih dahulu, yaitu ASSERT(foo, "", str); ).
Catatan: Ekspresi pesan pernyataan hanya dievaluasi dalam jalur kegagalan pernyataan.
extra diagnosticsJumlah nilai diagnostik tambahan yang sewenang -wenang dapat disediakan. Ini ditampilkan di bawah diagnostik ekspresi jika pemeriksaan gagal.
Catatan: Diagnostik tambahan hanya dievaluasi dalam jalur kegagalan pernyataan.
Ada penanganan khusus ketika errno disediakan: Nilai strerror ditampilkan secara otomatis.
Untuk memfasilitasi kemudahan integrasi ke dalam kode _VAL varian disediakan yang mengembalikan nilai dari ekspresi menegaskan. Nilai yang dikembalikan ditentukan sebagai berikut:
ASSERT_VAL(foo()); atau ASSERT_VAL(false); ) dalam ekspresi pernyataan, nilai ekspresi hanya dikembalikan.== ,! != , < , <= , > , >= , && , || , atau atau penugasan atau penugasan senyawa apa pun maka nilai operan kiri dikembalikan.& , | , ^ , << , >> , atau operator biner dengan prioritas di atas bitshift maka nilai seluruh ekspresi dikembalikan. Yaitu, ASSERT_VAL(foo() > 2); Mengembalikan hasil yang dihitung dari foo() dan ASSERT_VAL(x & y); Mengembalikan hasil yang dihitung dari x & y ;
Jika nilai dari ekspresi pernyataan yang dipilih untuk dikembalikan adalah lvalue, jenis panggilan pernyataan akan menjadi referensi LValue. Jika nilai dari ekspresi pernyataan adalah RValue maka jenis panggilan akan menjadi RValue.
namespace libassert {
[[nodiscard]] std::string stacktrace (
int width = 0 ,
const color_scheme& scheme = get_color_scheme(),
std::size_t skip = 0
);
template < typename T> [[nodiscard]] std::string_view type_name () noexcept ;
template < typename T> [[nodiscard]] std::string pretty_type_name () noexcept ;
template < typename T> [[nodiscard]] std::string stringify ( const T& value);
}stacktrace : Menghasilkan jejak tumpukan, format ke lebar yang diberikan (0 tanpa format lebar)type_name : Mengembalikan nama tipe tpretty_type_name : Mengembalikan nama jenis yang dipetik untuk tstringify : menghasilkan debug stringifikasi nilai namespace libassert {
void enable_virtual_terminal_processing_if_needed ();
inline constexpr int stdin_fileno = 0 ;
inline constexpr int stdout_fileno = 1 ;
inline constexpr int stderr_fileno = 2 ;
bool isatty ( int fd);
[[nodiscard]] int terminal_width ( int fd);
}enable_virtual_terminal_processing_if_needed : Aktifkan urutan pelarian ANSI untuk terminal pada windows, diperlukan untuk output warna.isatty : Mengembalikan true jika deskriptor file sesuai dengan terminalterminal_width : Mengembalikan lebar terminal yang diwakili oleh FD atau 0 pada kesalahan namespace libassert {
// NOTE: string view underlying data should have static storage duration, or otherwise live as
// long as the scheme is in use
struct color_scheme {
std::string_view string, escape, keyword, named_literal, number, punctuation, operator_token,
call_identifier, scope_resolution_identifier, identifier, accent, unknown, reset;
static const color_scheme ansi_basic;
static const color_scheme ansi_rgb;
static const color_scheme blank;
};
void set_color_scheme ( const color_scheme&);
const color_scheme& get_color_scheme ();
} Secara default color_scheme::ansi_rgb digunakan. Untuk menonaktifkan warna, gunakan color_scheme::blank .
set_color_scheme : Mengatur skema warna untuk penangan pernyataan default saat stderr adalah terminal namespace libassert {
void set_separator (std::string_view separator);
}set_separator : Mengatur pemisah antara ekspresi dan nilai dalam output diagnostik assersi. Default: => . Catatan: Tidak aman. namespace libassert {
enum class literal_format_mode {
infer, // infer literal formats based on the assertion condition
no_variations, // don't do any literal format variations, just default
fixed_variations // always use a fixed set of formats (in addition to the default format)
};
void set_literal_format_mode (literal_format_mode);
enum class literal_format : unsigned {
// integers and floats are decimal by default, chars are of course chars, and everything
// else only has one format that makes sense
default_format = 0 ,
integer_hex = 1 ,
integer_octal = 2 ,
integer_binary = 4 ,
integer_character = 8 , // format integers as characters and characters as integers
float_hex = 16 ,
};
[[nodiscard]] constexpr literal_format operator |(literal_format a, literal_format b);
void set_fixed_literal_format (literal_format);
}set_literal_format_mode : set apakah perpustakaan harus menunjukkan variasi literal atau menyimpulkannyaset_fixed_literal_format : atur konfigurasi format literal tetap, secara otomatis mengubah literal_format_mode; Perhatikan bahwa format default akan selalu digunakan bersama dengan orang lain namespace libassert {
enum class path_mode {
full, // full path is used
disambiguated, // only enough folders needed to disambiguate are provided
basename, // only the file name is used
};
LIBASSERT_EXPORT void set_path_mode (path_mode mode);
}set_path_mode : Mengatur mode pemendekan path untuk output pernyataan. Default: path_mode::disambiguated . namespace libassert {
enum class assert_type {
debug_assertion,
assertion,
assumption,
panic,
unreachable
};
struct LIBASSERT_EXPORT binary_diagnostics_descriptor {
std::string left_expression;
std::string right_expression;
std::string left_stringification;
std::string right_stringification;
};
struct extra_diagnostic {
std::string_view expression;
std::string stringification;
};
struct LIBASSERT_EXPORT assertion_info {
std::string_view macro_name;
assert_type type;
std::string_view expression_string;
std::string_view file_name;
std:: uint32_t line;
std::string_view function;
std::optional<std::string> message;
std::optional<binary_diagnostics_descriptor> binary_diagnostics;
std::vector<extra_diagnostic> extra_diagnostics;
size_t n_args;
std::string_view action () const ;
const cpptrace::raw_trace& get_raw_trace () const ;
const cpptrace::stacktrace& get_stacktrace () const ;
[[nodiscard]] std::string header ( int width = 0 , const color_scheme& scheme = get_color_scheme()) const ;
[[nodiscard]] std::string tagline ( const color_scheme& scheme = get_color_scheme()) const ;
[[nodiscard]] std::string location () const ;
[[nodiscard]] std::string statement ( const color_scheme& scheme = get_color_scheme()) const ;
[[nodiscard]] std::string print_binary_diagnostics ( int width = 0 , const color_scheme& scheme = get_color_scheme()) const ;
[[nodiscard]] std::string print_extra_diagnostics ( int width = 0 , const color_scheme& scheme = get_color_scheme()) const ;
[[nodiscard]] std::string print_stacktrace ( int width = 0 , const color_scheme& scheme = get_color_scheme()) const ;
[[nodiscard]] std::string to_string ( int width = 0 , const color_scheme& scheme = get_color_scheme()) const ;
};
} Debug Assertion failed at demo.cpp:194: void foo::baz(): Internal error with foobars
debug_assert(open(path, 0) >= 0, ...);
Where:
open(path, 0) => -1
Extra diagnostics:
errno => 2 "No such file or directory"
path => "/home/foobar/baz"
Stack trace:
#1 demo.cpp:194 foo::baz()
#2 demo.cpp:172 void foo::bar<int>(std::pair<int, int>)
#3 demo.cpp:396 main
Debug Assertion failed : assertion_info.action()demo.cpp:194 : assertion_info.file_name dan assertion_info.linevoid foo::baz() : assertion_info.pretty_functionInternal error with foobars : assertion_info.messagedebug_assert : assertion_info.macro_nameopen(path, 0) >= 0 : assertion_info.expression_string... : ditentukan oleh assertion_info.n_args yang memiliki jumlah total argumen yang diteruskan ke makro pernyataanopen(path, 0) : assertion_info.binary_diagnostics.left_expression-1 : assertion_info.binary_diagnostics.left_stringification0 => 0 tidak berguna)errno : assertion_info.extra_diagnostics[0].expression2 "No such file or directory" : assertion_info.extra_diagnostics[0].stringificationassertion_info.get_stacktrace() , atau assertion_info.get_raw_trace() untuk mendapatkan jejak tanpa menyelesaikannyaPembantu:
assertion_info.header() :
Debug Assertion failed at demo.cpp:194: void foo::baz(): Internal error with foobars
debug_assert(open(path, 0) >= 0, ...);
Where:
open(path, 0) => -1
Extra diagnostics:
errno => 2 "No such file or directory"
path => "/home/foobar/baz"
assertion_info.tagline() :
Debug Assertion failed at demo.cpp:194: void foo::baz(): Internal error with foobars
assertion_info.location() :
Catatan
Pemrosesan jalur akan dilakukan sesuai dengan mode jalur
demo.cpp:194
assertion_info.statement() :
debug_assert(open(path, 0) >= 0, ...);
assertion_info.print_binary_diagnostics() :
Where:
open(path, 0) => -1
assertion_info.print_extra_diagnostics() :
Extra diagnostics:
errno => 2 "No such file or directory"
path => "/home/foobar/baz"
assertion_info.print_stacktrace() :
Stack trace:
#1 demo.cpp:194 foo::baz()
#2 demo.cpp:172 void foo::bar<int>(std::pair<int, int>)
#3 demo.cpp:396 main
Libassert menyediakan titik kustomisasi untuk tipe yang ditentukan pengguna:
template <> struct libassert ::stringifier<MyObject> {
std::string stringify ( const MyObject& type) {
return ...;
}
};Secara default, tipe yang ditentukan pengguna seperti kontainer akan secara otomatis dapat secara otomatis.
Selain itu, LIBASSERT_USE_FMT dapat digunakan untuk memungkinkan libassert menggunakan fmt::formatter s.
Terakhir, jenis apa pun dengan operator<< kelebihan beban dapat dirangkai.
namespace libassert {
void set_failure_handler ( void (*handler)( const assertion_info&));
}set_failure_handler : Mengatur penangan pernyataan untuk program ini.Contoh penangan pernyataan yang mirip dengan pawang default:
void libassert_default_failure_handler ( const assertion_info& info) {
libassert::enable_virtual_terminal_processing_if_needed (); // for terminal colors on windows
std::string message = info. to_string (
libassert::terminal_width (libassert::stderr_fileno),
libassert::isatty (libassert::stderr_fileno)
? libassert::get_color_scheme ()
: libassert::color_scheme::blank
);
std::cerr << message << std::endl;
switch (info. type ) {
case libassert::assert_type::assertion:
case libassert::assert_type::debug_assertion:
case libassert::assert_type::assumption:
case libassert::assert_type::panic:
case libassert::assert_type::unreachable:
( void ) fflush (stderr);
std::abort ();
// Breaking here as debug CRT allows aborts to be ignored, if someone wants to make a
// debug build of this library
break ;
default :
std::cerr << " Critical error: Unknown libassert::assert_type " << std::endl;
std::abort ( 1 );
}
}Secara default libassert membatalkan dari semua jenis pernyataan. Namun, mungkin diinginkan untuk melempar pengecualian dari beberapa atau semua jenis pernyataan alih -alih dibatalkan.
Penting
Penangan Kegagalan tidak boleh kembali untuk assert_type::panic dan assert_type::unreachable .
Libassert mendukung breakpoint program tentang kegagalan pernyataan untuk membuat pernyataan lebih ramah debugger dengan melanggar garis pernyataan yang bertentangan dengan beberapa lapisan jauh di dalam callstack:

Fungsionalitas ini saat ini ikut serta dan dapat diaktifkan dengan mendefinisikan LIBASSERT_BREAK_ON_FAIL . Ini paling baik dilakukan sebagai bendera kompiler: -DLIBASSERT_BREAK_ON_FAIL atau /DLIBASSERT_BREAK_ON_FAIL .
Secara internal perpustakaan memeriksa presensi seorang debugger sebelum menjalankan instruksi untuk membubarkan debugger. Secara default cek hanya dilakukan sekali pada kegagalan pernyataan pertama. Dalam beberapa skenario mungkin diinginkan untuk mengkonfigurasi cek ini untuk selalu dilakukan, misalnya jika Anda menggunakan penangan pernyataan khusus yang melempar pengecualian alih-alih dibatalkan dan Anda mungkin dapat pulih dari kegagalan pernyataan yang memungkinkan kegagalan tambahan nanti dan Anda hanya melampirkan bagian debugger melalui menjalankan program Anda. Anda dapat menggunakan libassert::set_debugger_check_mode untuk mengontrol bagaimana cek ini dilakukan:
namespace libassert {
enum class debugger_check_mode {
check_once,
check_every_time,
};
void set_debugger_check_mode (debugger_check_mode mode) noexcept ;
}Perpustakaan juga memperlihatkan utilitas internalnya untuk menetapkan breakpoint dan memeriksa apakah program sedang debugged:
namespace libassert {
bool is_debugger_present () noexcept ;
}
# define LIBASSERT_BREAKPOINT () <...internals...>
# define LIBASSERT_BREAKPOINT_IF_DEBUGGING () <...internals...>API ini meniru API P2514, yang telah diterima untuk C ++ 26.
Catatan tentang constexpr : Untuk dentang dan MSVC Libassert dapat menggunakan intrinsik kompiler, namun, untuk perakitan inline GCC diperlukan. Majelis Inline tidak diizinkan dalam fungsi Constexpr pra-C ++ 20, namun, GCC mendukungnya dengan peringatan setelah GCC 10 dan perpustakaan dapat mengejutkan bahwa peringatan untuk GCC 12.
Mendefinisikan:
LIBASSERT_USE_MAGIC_ENUM : Gunakan ajaib enum untuk merangkai nilai enumLIBASSERT_DECOMPOSE_BINARY_LOGICAL : dekomposisi && dan ||LIBASSERT_SAFE_COMPARISONS : aktifkan perbandingan yang tidak ditandatangani dengan aman untuk ekspresi teruraiLIBASSERT_PREFIX_ASSERTIONS : awalan semua macro pernyataan dengan LIBASSERT_LIBASSERT_USE_FMT : Mengaktifkan integrasi libfmtLIBASSERT_NO_STRINGIFY_SMART_POINTER_OBJECTS : menonaktifkan stringifikasi konten pointer pintarCmake:
LIBASSERT_USE_EXTERNAL_CPPTRACE : Gunakan externam cpptrace alih -alih menambah perpustakaan dengan fetchcontentLIBASSERT_USE_EXTERNAL_MAGIC_ENUM : Gunakan Externam Magic Enum alih -alih Aquiring the Library dengan FetchContentCatatan
Karena preprosesor MSVC yang tidak sesuai, tidak ada cara mudah untuk memberikan pembungkus pernyataan. Untuk menggunakan Integrasi Perpustakaan Tes /Zc:preprocessor .
Libassert menyediakan integrasi Catch2 di libassert/assert-catch2.hpp :
# include < libassert/assert-catch2.hpp >
TEST_CASE ( " 1 + 1 is 2 " ) {
ASSERT ( 1 + 1 == 3 );
}
Saat ini satu -satunya makro yang disediakan adalah ASSERT , yang akan melakukan REQUIRE internal.
Catatan: Sebelum v3.6.0 Kode warna ANSI mengganggu pembungkus garis Catch2 sehingga warna dinonaktifkan pada versi yang lebih lama.
Libassert menyediakan integrasi gtest di libassert/assert-gtest.hpp :
# include < libassert/assert-gtest.hpp >
TEST (Addition, Arithmetic) {
ASSERT ( 1 + 1 == 3 );
}
Saat ini Libassert menyediakan ASSERT dan EXPECT makro untuk GTEST.
Ini tidak secantik yang saya inginkan, namun, itu menyelesaikan pekerjaan.
Target perpustakaan ini> = C ++ 17 dan mendukung semua kompiler utama dan semua platform utama (Linux, MacOS, Windows, dan Mingw).
Catatan: Perpustakaan mengandalkan beberapa ekstensi kompiler dan fitur spesifik kompiler sehingga tidak kompatibel dengan -pedantic .
Dengan cmake fetchcontent:
include (FetchContent)
FetchContent_Declare(
libassert
GIT_REPOSITORY https://github.com/jeremy-rifkin/libassert.git
GIT_TAG v2.1.2 # <HASH or TAG>
)
FetchContent_MakeAvailable(libassert)
target_link_libraries (your_target libassert::assert)Catatan: Pada Windows dan MacOs beberapa pekerjaan tambahan disarankan, lihat Platform Logistik di bawah ini.
Pastikan untuk mengonfigurasi dengan -DCMAKE_BUILD_TYPE=Debug atau -DDCMAKE_BUILD_TYPE=RelWithDebInfo untuk simbol dan informasi garis.
git clone https://github.com/jeremy-rifkin/libassert.git
git checkout v2.1.2
mkdir libassert/build
cd libassert/build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j
sudo make installMenggunakan melalui cmake:
find_package (libassert REQUIRED)
target_link_libraries (<your target > libassert::assert) Pastikan untuk mengonfigurasi dengan -DCMAKE_BUILD_TYPE=Debug atau -DDCMAKE_BUILD_TYPE=RelWithDebInfo untuk simbol dan informasi garis.
Atau kompilasi dengan -lassert :
g++ main.cpp -o main -g -Wall -lassert
./mainJika Anda mendapatkan kesalahan di sepanjang baris
error while loading shared libraries: libassert.so: cannot open shared object file: No such file or directory
Anda mungkin harus menjalankan sudo /sbin/ldconfig untuk membuat tautan yang diperlukan dan memperbarui cache sehingga sistem dapat menemukan libcpptrace.so (saya harus melakukan ini di ubuntu). Hanya saat memasang sistem di seluruh sistem. Biasanya Paket Anda melakukan ini untuk Anda saat menginstal perpustakaan baru.
git clone https: // github.com / jeremy - rifkin / libassert.git
git checkout v2. 1.2
mkdir libassert / build
cd libassert / build
cmake . . - DCMAKE_BUILD_TYPE = Release
msbuild libassert.sln
msbuild INSTALL.vcxprojCatatan: Anda harus menjalankan sebagai administrator di pengembang PowerShell, atau menggunakan vcvarsall.bat didistribusikan dengan Visual Studio untuk mendapatkan variabel lingkungan yang benar.
Untuk menginstal hanya untuk pengguna lokal (atau awalan khusus):
git clone https://github.com/jeremy-rifkin/libassert.git
git checkout v2.1.2
mkdir libassert/build
cd libassert/build
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX= $HOME /wherever
make -j
sudo make installMenggunakan melalui cmake:
find_package (libassert REQUIRED PATHS $ENV{HOME} /wherever)
target_link_libraries (<your target > libassert::assert)Menggunakan secara manual:
g++ main.cpp -o main -g -Wall -I$HOME/wherever/include -L$HOME/wherever/lib -lassert
Untuk menggunakan pustaka tanpa cmake pertama-tama ikuti instruksi instalasi di instalasi sistem, instalasi pengguna lokal, atau manajer paket.
Gunakan argumen berikut untuk dikompilasi dengan libassert:
| Penyusun | Platform | Dependensi |
|---|---|---|
| GCC, Clang, Intel, dll. | Linux/MacOS/UNIX | -libassert -I[path] [cpptrace args] |
| Mingw | Windows | -libassert -I[path] [cpptrace args] |
| MSVC | Windows | assert.lib /I[path] [cpptrace args] |
| dentang | Windows | -libassert -I[path] [cpptrace args] |
Untuk placeholder [path] di -I[path] dan /I[path] , tentukan jalur ke folder sertakan yang berisi libassert/assert.hpp .
Jika Anda menautkan secara statis, Anda juga perlu menentukan -DLIBASSERT_STATIC_DEFINE .
Untuk placeholder [cpptrace args] merujuk ke dokumentasi CPPTRACE.
Libassert tersedia melalui Conan di https://conan.io/center/recipes/libassert.
[requires]
libassert/2.1.2
[generators]
CMakeDeps
CMakeToolchain
[layout]
cmake_layout
# ...
find_package (libassert REQUIRED)
# ...
target_link_libraries (YOUR_TARGET libassert::assert) vcpkg install libassert
find_package (libassert CONFIG REQUIRED)
target_link_libraries (YOUR_TARGET PRIVATE libassert::assert)Windows dan MacO membutuhkan sedikit pekerjaan tambahan untuk mendapatkan semuanya di tempat yang tepat
Menyalin pustaka .dll di windows:
# Copy the assert.dll on windows to the same directory as the executable for your_target.
# Not required if static linking.
if ( WIN32 )
add_custom_command (
TARGET your_target POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE:libassert::assert>
$<TARGET_FILE_DIR:your_target>
)
endif ()Di MacOS, disarankan untuk menghasilkan file DSYM yang berisi informasi debug untuk program Anda:
Di xcode cmake ini bisa dilakukan
set_target_properties (your_target PROPERTIES XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT "dwarf-with-dsym" ) Dan di luar xcode ini dapat dilakukan dengan dsymutil yourbinary :
# Create a .dSYM file on macos. Currently required, but hopefully not for long
if ( APPLE )
add_custom_command (
TARGET your_target
POST_BUILD
COMMAND dsymutil $<TARGET_FILE:your_target>
)
endif () Perpustakaan ini bukan pengganti drop-in untuk <cassert> . -DLIBASSERT_LOWERCASE dapat digunakan untuk membuat alias kecil untuk macro pernyataan tetapi perlu diketahui bahwa ASSERT Libassert masih diperiksa dalam rilis. Untuk mengganti <cassert> Gunakan dengan libassert, ganti assert dengan DEBUG_ASSERT atau buat alias di sepanjang baris berikut:
# define assert (...) DEBUG_ASSERT(__VA_ARGS__) Satu hal yang perlu diperhatikan: mengesampingkan assert Cassert secara teknis tidak diizinkan oleh standar, tetapi ini seharusnya tidak menjadi masalah bagi kompiler waras.
Tidak, belum.
cpp-sort Morwenn Bahkan dengan konstruksi seperti assert_eq , diagnostik pernyataan sering kurang. Misalnya, dalam karat nilai kiri dan kanan ditampilkan tetapi bukan ekspresi itu sendiri:
fn main ( ) {
let count = 4 ;
assert_eq ! ( count , 2 ) ;
} thread 'main' panicked at 'assertion failed: `(left == right)`
left: `4`,
right: `2`', /app/example.rs:3:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Ini tidak bermanfaat seperti yang seharusnya.
Fungsionalitas bahasa lain / pustaka standar mereka menyediakan:
| C/C ++ | Karat | C# | Jawa | Python | Javascript | Libassert | |
|---|---|---|---|---|---|---|---|
| String ekspresi | ✔️ | ✔️ | |||||
| Lokasi | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
| Tumpukan jejak | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | |
| Pesan penegasan | ** | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
| Diagnostik tambahan | * | * | * | * | ✔️ | ||
| Spesialisasi biner | ✔️ | ✔️ | ✔️ | ||||
| Dekomposisi ekspresi otomatis | ✔️ | ||||||
| String sub-ekspresi | ✔️ |
* : Mungkin melalui pemformatan string tetapi itu adalah sub-ideal.
** : assert(expression && "message") umumnya digunakan tetapi ini adalah sub-ideal dan hanya memungkinkan pesan literal string.
Ekstra:
| C/C ++ | Karat | C# | Jawa | Python | Javascript | Libassert | |
|---|---|---|---|---|---|---|---|
| Sorot sintaks | ? | ✔️ | |||||
| Konsistensi pemformatan literal | ✔️ | ||||||
| String ekspresi dan nilai ekspresi di mana -mana | ✔️ | ||||||
| Nilai pengembalian dari Assert untuk memungkinkan Assert diintegrasikan ke dalam ekspresi inline | ✔️ |