Frage

In C und C ++ assert ist ein sehr Schwergewichts-Routine, ein Fehler beim Schreiben des Programms stdout und endet. In unserer Anwendung haben wir ein viel robuster Ersatz für assert umgesetzt und es sein eigenes Makro gegeben. Alle Anstrengungen gemacht worden assert mit unserem Makro zu ersetzen, aber es gibt noch viele Möglichkeiten, assert wieder eingeführt werden kann (beispielsweise aus dem internen Bibliothek von Drittanbietern, naiver Injektion usw.)

Alle Vorschläge, wie wir reduzieren können, zu begrenzen oder sogar Anwendungen von assert auszurotten? Die beste Antwort wird sein der Compiler für uns fangen, so dass wir wie wir zur Zeit nicht so viel die Code-Basis babysitten müssen.

War es hilfreich?

Lösung

Ich bin mir nicht sicher, ob ich wirklich das Problem verstehen, eigentlich. Behauptet sind nur teuer, wenn sie gehen, was ohnehin in Ordnung ist, da man jetzt in einer Ausnahmesituation ist.

assert nur aktiviert, in Debugbuilds, so das Release-Build von einer Drittanbieter-Bibliothek verwenden. Aber wirklich, behauptet sollte jeden Moment abgehend nicht werden.

Andere Tipps

Es kann nützlich sein, auf der Einbau-Behauptung Anlage zu verbessern (Stack-Traces zur Verfügung zu stellen, Core-Dumps, wer weiß). In diesem Fall, wenn Sie Probleme haben, Ihre Entwickler zu folgen sind mit, was Standards Sie haben (wie „statt assert() Verwendung SUPER_ASSERT()“ oder was auch immer), können Sie einfach Ihre eigenen assert.h Header in dem Pfad enthalten in Führung gebracht, der Laufzeitverzeichnis des Compilers von Headern.

Das wird ziemlich garantieren, dass jeder kann den Standard assert() Makro wird einen Compiler-Fehler oder Ihre Behauptung Funktionalität erhalten (je nachdem, was Sie Ihren assert.h Header tun haben).

Es wäre (zumindest teilweise) davon abhängen, was Sie ändern. Unter der Annahme, dass Sie nichts dagegen seine normale Nachricht auszudrucken, und vor allem wollen, um loszuwerden, es abort() nennen, könnte man bedenkt, assert() allein zu lassen und stattdessen eine eigene Version von abort() definieren.

In der Theorie, das zu tun ist nicht tragbar - aber in Wirklichkeit ist abort() eine ziemlich normale Funktion in der Standard-Bibliothek, und wenn Sie Ihre eigenen Link stattdessen erhalten Sie sein Verhalten. Manchmal (vor allem einige Microsoft-Linker) Sie haben ein wenig Arbeit zu tun, um den Linker zu erhalten zusammenzuarbeiten, um deren abort() mit Ihnen zu ersetzen, aber es ist selten sehr schwierig.

Ich glaube, Ihre Frage völlig gültig ist. Wenn Sie eine eigene Fehlerbehandlung implementiert haben, können Sie wollen:

  1. Immer Trigger behauptet auch in Release-Builds.
  2. Implementieren bessere Fehlerberichterstattung im Fall eine Assertion auslöst. Möglicherweise möchten Sie Fehlerberichte senden oder Schreiben von Dateien zu protokollieren.

aber sagen, dass ich sehe keine Lösung, die immer funktioniert.

  • Wenn Sie Glück haben, werden die Bibliotheken von Drittanbietern ASSERT-Makros verwenden, die Sie selbst, solange die Datei dieses Makro eine Art #pragma once oder #ifndef __HEADERFILE_H__ #define __HEADERFILE_H__ Bestimmung gegen mehrere Inklusion hat die Definition neu definieren kann. Fügen Sie die Header-Datei separat, neu definieren ASSERT und du bist gut.

  • Wenn sie direkt assert.h oder cassert enthalten können Sie nur den Code Patch, denke ich. Machen minimale Änderungen am Code, speichern Sie die Änderungen als Patch-Dateien und wenn Sie die Bibliothek aktualisieren hoffen, dass der Patches immer noch funktionieren. Fügen Sie den Patches zur Versionskontrolle.

Wenn das nicht funktioniert, überdenken die Frage, ob Sie wirklich interne müssen behauptet in Bibliotheken von Drittanbietern. Schiff Release baut nur, wird diese loszuwerden, die behauptet, und fügen Sie Ihre ASSERTs für Korrektheit in Ihrem Code zu überprüfen. Überprüfen Sie für die Gültigkeit der Rückgabewerte. Wenn eine solche ASSERT ausgelöst wird, können Sie immer noch den Code von Drittanbietern tauchen in, um zu sehen, was das Problem verursacht hat.

Ich denke, die Frage gültig ist.

Meine ganz eigene assert expandiert nach asm ( „int3“), wenn ausgelöst, die zu einem Haltepunkt entsprechen. Ich fand auch, dass wesentlich mehr nützlich für die Fehlersuche als eine einfache Terminierung.

ich es einfach "ASSERT ()" genannt, statt der normalen "assert ()" und vermied die Verwendung von assert () überhaupt.

Der offensichtlichste Ansatz scheint zu sein, Ihre eigene Version zu geben, seinen eigenen Namen geltend machen, leicht von assert(). Dann können Sie den Text, schauen Linker-Nachrichten suchen, usw. für die Zeichenkette „_assert“ und Sie wissen, Sie haben ein Problem, wenn Sie es sehen.

In meinem eigenen Code, verwende ich immer Assert(), die meine eigene Funktion erweitert, die eine Behauptung führt, oder erweitern für das Release-Build ((void)0). Der Compiler wird den ((void)0) Ausdruck in nichts drehen, aber es zählt immer noch als Ausdruck. So

Assert(3 == x);

wird sich in

((void)0);

und das Semikolon hat einen Platz zu gehen.

By the way, ich habe einmal auf einer GUI-Anwendung, bei der die Assertion ein spezieller GUI modaler Popup-Dialog war. Sie haben drei Möglichkeiten: Ignorieren, Ignorieren für immer, oder brechen. Ignorieren würde die Assertion ignorieren und am Laufen zu halten. Ignorieren für immer würde ein Flag gesetzt, und bis Sie das Programm im Debugger neu gestartet, dass assert würde nicht mehr schießen. Pause würde die Assertion in den Debugger zu brechen.

Ich erinnere mich nicht, wie sie garantiert, dass jeder Assertion seine eigene Flagge hatte. Vielleicht, wenn Sie die Assert () schrieb rufen Sie eine eindeutige Ganzzahl angeben hatte? Es wäre schön, wenn es mehr automatische ist als das. Ich bin mir ziemlich sicher, dass die tatsächliche implmentation ein Bit-Vektor war, und es würde das Bit gesetzt, wenn Sie für immer gewählt ignorieren.

assert() ist in der Regel #define'd seine ((void) 0) für die Freigabe-Code (#define NDEBUG), so gibt es keinen Overhead bei allen .

Wenn Sie eine Testversion verwenden, ist die Performance-Overhead Ihre Fähigkeit, für die Prüfung zu verletzen, realistisch zu sein?

Sie scheinen die Tatsache zu fehlen, dass der Code von Drittanbietern wird höchstwahrscheinlich unter der Annahme von „Standard“ assert Verhalten geschrieben. D. h der Code erwartet das Programm über gescheiterte Behauptung zu beenden. Der Code, der die Behauptung folgt normalerweise nicht und wird nicht korrekt funktionieren, wenn der geltend gemachte Zustand gebrochen wird. In 99 von 100 Fällen wird es nicht funktionieren. In 99 von 100 Fällen es einfach abstürzen wird, das heißt das Programm beenden trotzdem.

Zu glauben, dass das assert Verhalten in Code von Drittanbietern durch zwingend Sie irgendwie das Programm machen leben länger naiv ist am besten.

Wenn Quellcode ist unter Ihrer Kontrolle:

#define NDEBUG
// Before
#include <assert.h>
// Or other header that includes assert.h

oder mit vorkompilierte Header oder kompilieren Optionen NDEBUG definieren.

Für Dritt Teil Binärdateien, verwenden Sie die Release-Version von ihnen.

Finden assert in der Bibliothek Header (vorausgesetzt, sie sind echte Dateien auf dem Dateisystem) und ersetzen Sie es mit einer ungültigen Sache

// #define assert(condition) ... /* old definition */
#define assert(condition) ((condition) & "PLEASE DO NOT USE ASSERT" = 42)
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top