Man muss zurückblicken, um voranzukommen. Werfen wir einen Blick zurück auf C, C++ und wie sich die Sprache anfühlt, um dann zu moderneren Sprachen überzugehen. Lassen Sie uns loslegen!
GCC
GCC ist der Gnu Compiler zum Kompilieren der Programmiersprache C. C ist eine allgemeine imperative Programmiersprache mit einem statischen Typsystem. Klingt großartig, nicht wahr! Lassen Sie uns Hello World erstellen.
#include <stdio.h>
int
main (void)
{
printf("Hello, world!n");
return 0;
}
Auf einem Mac müssen Sie nichts installieren. Der C-Compiler ist bereits verfügbar, so dass Sie einfach Folgendes eingeben können.
$ gcc -Wall hello.c -o hello
$ ./hello
Hello, world!
# determine file type
$ file hello
hello: Mach-O 64-bit executable x86_64
# determine file size
$ ls -alh hello
-rwxr-xr-x 1 dennis staff 8.2K Nov 28 18:05 hello
Unsichere Operationen
Lassen Sie uns etwas Unsicheres ausprobieren! Erstellen wir ein Array mit 5 Elementen und greifen wir auf das 6. Was wird passieren?
#include <stdio.h>
int
main (void)
{
int arr[] = {1,2,3,4,5};
printf("arr [0] is %dn", arr[0]);
printf("arr [1] is %dn", arr[1]);
printf("arr [2] is %dn", arr[2]);
printf("arr [3] is %dn", arr[3]);
printf("arr [4] is %dn", arr[4]);
// surprise!!
printf("arr [5] is %dn", arr[5]);
return 0;
}
Ausgänge:
$ gcc -Wall unsafe.c -o unsafe
$ ./unsafe
arr [0] is 1
arr [1] is 2
arr [2] is 3
arr [3] is 4
arr [4] is 5
arr [5] is 32766
Die Anwendung läuft, es gibt keine 'IndexOutOfBoundsException'.
SegFault
Lassen Sie uns in einen Teil des Speichers schreiben, auf den wir keinen Zugriff haben. Das Programm wird abstürzen. Dies wird dadurch verursacht, dass das Programm versucht, in einen Speicherbereich (Segment) zu schreiben, der nicht erlaubt ist. In C ist das recht einfach zu bewerkstelligen.
#include <stdio.h>
int main()
{
int arr[] = {1,2,3,4,5};
printf("arr [0] is %dn", arr[0]);
printf("arr [1] is %dn", arr[1]);
printf("arr [2] is %dn", arr[2]);
printf("arr [3] is %dn", arr[3]);
printf("arr [4] is %dn", arr[4]);
// crash segfault
arr[6] = 7;
printf("arr [6] is %dn", arr[6]);
return 0;
}
Lassen Sie uns kompilieren und ausführen:
$ gcc -Wall segfault.c -o segfault
./segfault
make: *** [run] Abort trap: 6
C++
Lassen Sie uns etwas Ähnliches mit C++ versuchen.
#include <iostream>
int main()
{
std::cout << "Hello, World!";
return 0;
}
Auf einem Mac müssen Sie nichts installieren. Der C++-Compiler ist bereits verfügbar, so dass Sie einfach Folgendes eingeben können.
$ g++ -Wall hello.cpp -o hello
$ ./hello
Hello, world!
# determine file type
$ file hello
hello: Mach-O 64-bit executable x86_64
# determine file size
$ ls -alh hello
-rwxr-xr-x 1 dennis staff 15K Nov 28 17:48 hello
Unsichere Operationen
Lassen Sie uns etwas Unsicheres ausprobieren! Erstellen wir ein Array mit 5 Elementen und greifen wir auf das 6. Was wird passieren?
#include <iostream>
int main()
{
int arr[] = {1,2,3,4,5};
std::printf("arr [0] is %dn", arr[0]);
std::printf("arr [1] is %dn", arr[1]);
std::printf("arr [2] is %dn", arr[2]);
std::printf("arr [3] is %dn", arr[3]);
std::printf("arr [4] is %dn", arr[4]);
// surprise!!
std::printf("arr [5] is %dn", arr[5]);
return 0;
}
Ausgänge:
$ g++ -Wall unsafe.cpp -o unsafe
$ ./unsafe
arr [0] is 1
arr [1] is 2
arr [2] is 3
arr [3] is 4
arr [4] is 5
arr [5] is 32766
Es geschah das Gleiche wie in C.
SegFault
Lassen Sie uns den Segmentierungsfehler in C++ ausprobieren
#include <iostream>
int main()
{
int arr[] = {1,2,3,4,5};
std::printf("arr [0] is %dn", arr[0]);
std::printf("arr [1] is %dn", arr[1]);
std::printf("arr [2] is %dn", arr[2]);
std::printf("arr [3] is %dn", arr[3]);
std::printf("arr [4] is %dn", arr[4]);
// crash segfault
arr[6] = 5;
std::printf("arr [6] is %dn", arr[6]);
return 0;
}
Ausgänge:
$ gcc -Wall segfault.cpp -o segfault
./segfault
make: *** [run] Abort trap: 6
Fazit
In diesem Blog haben wir versucht, ein paar kleine Programme zu erstellen. Wir haben helloworld sowohl in C als auch in C++ erstellt und das hat hervorragend funktioniert. Beide Sprachen erzeugten sehr kleine Binärdateien und starteten sofort. Dann haben wir versucht, etwas Unsicheres zu tun und eine Speicherstelle außerhalb der Grenzen aus einem Array zu lesen. Der Compiler erstellte trotzdem eine Binärdatei und erlaubte eine Operation, die außerhalb der Grenzen lag. Schließlich schrieben wir an eine Speicherstelle außerhalb der Grenzen, was zu einem Segmentierungsfehler führte und die Anwendung zum Absturz brachte.
Natürlich sind dies triviale Beispiele und der Fehler ist leicht zu erkennen und zu beheben. Wenn die Codebasis größer ist, wird es schwieriger, die Anwendung zu reparieren. C und C++ haben uns so weit gebracht, aber es ist an der Zeit für modernere Sprachen, die uns helfen, diese Fehler abzufangen, und die es uns dennoch ermöglichen, leistungsstarke Anwendungen zu erstellen.
Das nächste Mal werden wir uns die Programmiersprache
Verfasst von
Dennis Vriend
Contact
