Beschränken Sie einige C -Strukturen auf bestimmte Regionen des Haufens.
Wenn Sie C zur Implementierung einer Laufzeit für eine Programmiersprache verwenden, möchten wir möglicherweise interne Laufzeitdatenstrukturen (mit malloc / free oder einer Art Speicherpool zugewiesen oder möglicherweise von einem abgefallenen Bild mmap ) von Benutzerobjekten unterscheiden, die in einem GC -verwalteten Heap zugewiesen wurden.
In Mono repräsentiert die Laufzeit verwaltete Objekte, die von System.Object mit einem C struct typedef struct _MonoObject { ... } MonoObject abgeleitet sind. Mono verwendet die Konvention, dass eine Klasse der Klasse T der Klasse T vom Typ T vom Typ T ist:
struct _MonoString {
MonoObject obj ; /* System.String derives from System.Object */
...
}; Mono wechselt zu einem Regime, in dem Hinweise auf das Memory MonoObject *ptr von den Laufzeiten indirekt über die Handles 1 : MonoObjectHandle h zugreifen müssen
Dieses Paket bietet eine Bibliothek, in der C -Dateien analysiert werden, um Orte zu finden, an denen Rohzeiger auf verwalteten Speicher verwendet werden.
So kann man Centrinel- und Centrinel-Report-Check ein Autotools-Projekt verwenden, um die C-Compiler-Aufrufe abzufangen:
# assuming you have GHC and cabal installed
$ pushd $CENTRINEL_DIR # go to the centrinel source directory
$ echo "Building Centrinel"
$ cabal sandbox init
$ cabal install happy
$ cabal install alex
$ cabal install --dependencies-only
$ cabal configure
$ cabal build
$ popd
$ echo Building project using "bear"
$ pushd $SRC_DIR
$ ./autoconf ...
$ bear make
# produces a compile_commands.json file
$ popd
$ cd $CENTRINEL_DIR
$ curl -o centrinel-report.tar.gz https://github.com/lambdageek/centrinel-report/releases/download/v0.3.1/centrinel-report.tar.gz
$ tar xvzf centrinel-report.tar.gz
# writes a skeleton HTML report to centrinel-report/
$ cabal run centrinel -- --project $SRC_DIR/compile_commands.json --exclude $SRC_DIR/thirdparty --format json --output centrinel-report/centrinel-report.json
# produces centrinel-report/centrinel-report.json
$ cd centrinel-report && python -m SimpleHTTPServer 8000
# go look at http://localhost:8000/
Dies ist ein frühzeitiger Prototyp, daher ist das Setup ein wenig involviert.
Sie benötigen eine aktuelle GHC (getestet mit GHC 8.2.x, GHC 8.0.x und 7.10.x) und Cabal.
Abhängigkeiten: Dieses Programm verwendet die language-c -Bibliothek für C -Parsen - Sie benötigen den installierten alex Lexer und happy Parser (entweder systemweit oder im Sandkasten für dieses Repository). Die folgenden Schritte richten eine Sandbox ein und installieren die benötigten Programme darin. (Sie brauchen alex nicht und happy , die Analyse durchzuführen, nur um den Analysator Binary aufzubauen.)
git clone https://github.com/lambdageek/centrinel.git
cd centrinel
cabal sandbox init
cabal install happy
cabal install alex
cabal install --dependencies-only
cabal configure
cabal build
cabal run centrinel -- --helpinclude/centrinel.h Header Centrinel stützt sich auf einige __attribute__((...)) Attribute, und einige Präprozessor definiert, um zu sagen, was zu analysieren ist. Wenn sich Centrinel auf den C -Präprozessor Centrinel aufruft, enthält es automatisch die Datei include/centrinel.h vor dem Benutzercode. Wenn der cabal run centrinel -Befehl wie oben aus einem Sandkasten aus dem Laufen aus einer Sandbox läuft, stellt der Befehl Cabal Run sicher, dass Centrinel diese Datei finden kann. Wenn Sie stattdessen cabal install verwenden, wird der Centrinel -Header in das Cabal -Datenverzeichnis kopiert, und die gebaute centrinel -Binärin wird auf diesen Ort verweisen, selbst wenn Sie anschließend die Binärdatum bewegen.
Dieser Header definiert __CENTRINEL__ bis 1 um anzuzeigen, dass Centrinel läuft; __CENTRINEL_MANAGED_ATTR -Attribut und __CENTRINEL_MANAGED_REGION -Attributspezifizierer, mit dem Sie Ihre Strukturen und Makros mit Anmerkungen versehen können, um bestimmte GCC-Primitive zu definieren, die nicht von language-c verstanden werden.
Der Header ist automatisch von Centrinel enthalten, Sie müssen ihn nicht explizit einbeziehen.
Sie sollten jetzt in der Lage sein, mit cabal run centrinel -- [ARGS] (oder cabal repl wenn Sie die verschiedenen Schritte separat ausführen möchten) mit ihm herumspielen können. Darüber hinaus gibt es ein Skript centrinelcc , das als CC verwendet werden kann, um Invocations als Drop-In-Ersatz für gcc oder clang make .
Verwendung: centrinel [--output FILE] -- CFLAGS CFILE
Das Programm versteht ein Modikum der cc -Befehlszeilenoptionen wie -D und -I und -U und wird andere an den Präprozessor übergeben. Einige Optionen, die für die Vorverarbeitung nicht sinnvoll sind (wie -c oder -MT werden verstanden und stillschweigend fallen). Standardmäßig werden die Ergebnisse auf STDOut gedruckt. Um sie zu einer Datei zu leiten, fügen Sie eine Option --output FILE hinzu.
$ cabal run centrinel -- c-examples/attrib.c
Errors:
c-examples/attrib.c:28: (column 2) [WARNING] >>> Region mismatch: Region 1 and Region 2
Additional locations:
c-examples/attrib.c:8: (column 2)
c-examples/attrib.c:13: (column 1)
c-examples/attrib.c:27: (column 1)
c-examples/attrib.c:35: (column 5) [ERROR] >>> Naked pointer(s) to managed object(s) found in declaration
Pointer to managed heap XP
in 0th argument 'x' at c-examples/attrib.c:35: (column 13)
in function declaration 'foo'
c-examples/attrib.c:37: (column 11) [ERROR] >>> Naked pointer(s) to managed object(s) found in declaration
Pointer to managed heap struct Y *
in return type
in function declaration 'bar'
Pointer to managed heap XP
in 1st argument 'x' at c-examples/attrib.c:37: (column 26)
in function declaration 'bar'
c-examples/attrib.c:39: (column 5) [ERROR] >>> Naked pointer(s) to managed object(s) found in declaration
Pointer to managed heap XP
in 0th argument 'x' at c-examples/attrib.c:33: (column 28)
in type defined at c-examples/attrib.c:33: (column 1)
at c-examples/attrib.c:39: (column 10)
in 0th argument 'f' at c-examples/attrib.c:39: (column 19)
in function declaration 'baz'
Hinweis : Wenn Sie eine Option übergeben müssen, die mit einem Armaturenbrett beginnt - Sie verwenden cabal run , sollten Sie schreiben -- : Einmal für Cabal und einmal für Centrinel: cabal run -- -- -DFOO -I../.. c-examples/attrib.c )
Verwendung: centrinel [--output FILE] --project compile_commands.json
Eine Klangkompilierungsdatenbank ist eine JSON -Datei, die einen Satz von Compiler -Aufrufe angibt. Tools wie cmake oder Bär können verwendet werden, um die Kompilierungsdatenbank (normalerweise als compile_commands.json bezeichnet) zu generieren. Centrinel kann die Datenbank mit der Option --project verwenden:
$ bear make -C some_project_directory # Note: doesn't work on OSX with System Integrity Protection
$ cabal run centrinel -- --project compile_commands.json
CC in einem Make Die scripts/centrinelcc können als Wert der CC -Variablen für make verwendet werden. Es wird zuerst den realen Compiler ausführen (angegeben von der REAL_CC -Umgebungsvariablen oder cc , falls dies nicht festgelegt ist) und wenn die Kompilierung erfolgreich ist, wird centrinel aufgerufen (die auf dem Weg sein muss)
Diese Schritte sind noch nicht automatisiert
$ cabal install
$ cp dist/build/centrinel/centrinel [somewhere on your PATH]
$ cp scripts/centrinelcc [somewhere on your PATH]
$ export REAL_CC=/path/to/your/cc # if unset, defaults to 'cc'
$ make CC=centrinelcc
Standardmäßig verwendet Centrinel den Wert der REAL_CC -Umgebungsvariable, um den Präprozessor auszuführen, oder cc falls nicht festgelegt. Eine andere Möglichkeit, den Compiler anzugeben, ist die Verwendung der CC-Option --use-cc CC , die Vorrang vor der Umgebungsvariablen hat.
Experimentell : Mit --format json Centrinel schreibt Analyseergebnisse als JSON -Blob (dessen Format momentan recht im Fluss ist). Der Blob kann mit dem Centrinel-Report konsumiert werden
Mit --exclude DIR (die mehrmals angegeben werden kann) werden alle Eingabedateien, die sich in DIR oder einem seiner Unterverzeichnisse befinden, nicht analysiert. (Funktioniert beide mit -- CFLAGS CFILE -Modus und mit --project JSON_FILE ).
Regionalanmerkungen zu Strukturdefinitionen (angegeben durch __attribute__((__region(N))) mit ganzzahliger N ) werden mit Regionen einheitlich sein, die für das erste Mitglied der Struktur abgeleitet wurden (vorausgesetzt, es ist ein weiterer Strukturart) und Konflikte werden gemeldet.
Zeiger auf Strukturen in der Region __CENTRINEL_MANAGED_REGION (definiert als __region(1) in include/centrinel.h ) löst einen Fehler aus, wenn sie in einem Funktionsprototyp (entweder eine Definition oder eine Definition) überall auftreten.
Überprüfung von Funktionskörpern zur Verwendung von __CENTRINEL_MANAGED_REGION -Zeiger.
Eine Möglichkeit, gesegnete Funktionen/Strukturen zu kommentieren, die Zeiger auf den verwalteten Heap manipulieren dürfen, ohne einen Fehler mit __CENTRINEL_SUPPRESS_ATTR(1) , der angewendet werden kann:
{
l: __CENTRINEL_SUPPRESS_ATTR ( 1 ) ;
/* your code that manipulated managed objecs */
} int __CENTRINEL_SUPPRESS_ATTR ( 1 ) foo (...); /* no warnings about pointers in ... */__CENTRINEL_SUPPRESS_ATTR(0) verwendet werden, um die Überprüfung in einem unterdrückten Kontext zurückzudrehen. Dies ist nützlich, um beispielsweise die Makroerweiterung zu erhalten: Sie möchten, dass der Körper des Makros vertrauen wird, sodass die Zeigerprüfung unterdrückt wird, die Argumente sind jedoch nicht unterdrückt, damit sie überprüft werden.1 : Ein sofortiger Vorteil ist, dass wir, wenn eine Müllsammlung während des Laufens des nativen Laufzeitcodes stattfindet, das referenzierte Objekt nicht anpassen müssen, was die Fragmentierung verringern kann. ↩