Forum: Compiler & IDEs Visual C++ Best Practise / Kompendium


von asd (Gast)


Lesenswert?

Hallo,

welches Busch oder welche andere Quelle würdet ihr empfehlen für die 
Frage was man alles beachten muss wenn man weit verbreitete C++ Library 
Funktionen benutzt. Z.B. wenn man Dateien öffnet und benutzt. Was ich 
konkret hänge ist die Frage, wenn man eine Datei öffnet und einen File 
Pointer bekommt der nicht der NULL Pointer ist, ist dann alles ok oder 
muss man dann doch noch den Statuswert testen? Und was muss man sonst 
noch beachten an exotischen Sonderfällen die auftreten könnten? (Datei 
liegt auf einem Samba Share der ein ext3 oder NTFS Dateisystem hat, 
dessen Rechte plötzlich..., und das Netzwerk hängt ein wenig, kommt aber 
wieder, oder was anders extotisches. Das da Tipps gibt wie: Wenn man 
einen File Handler bekommt, muss man doch noch dieses und jenes beachten 
weil meist geht es gut aber es könnte doch sein dass...)

Einfach ein Kompendium über die Sachen die man beim professionellen 
Programmieren beachten muss, die nicht Teil der Grundlagen-Vorlesung 
waren.
Die bei einfachen Situationen egal sind, aber wenn man alle Spezialfälle 
abdecken will braucht man mehr Hintergrund-Infos. Gerne auch speziell zu 
Windows 7-10 und Visual C++.

Ich meine jetzt nicht so abstrakte Sachen wie "continuous integration" 
oder "clean code" sondern konkret Fragen wie: Was muss man beachten wenn 
man die lib-Funktionen benutzt und welche Methoden oder libs haben 
welche Vor- und Nachteile (z.B. wenn es mehrere Methoden oder libs gibt 
mit denen man auf Dateien zugreifen kann, um bei dem Beispiel zu 
bleiben). Für ein altes Unix mit C hatte ich mal so ein Buch, aber was 
gibt es für Windows 7-10 und Visual C++?

von M.K. B. (mkbit)


Lesenswert?

asd schrieb:
> aber was gibt es für Windows 7-10 und Visual C++

Ich hab kein konkretes Buch, weil ich mir immer die Dokumentation 
durchlese. Prinzipiell kann man sich dann nur auf das verlassen, was in 
der Dokumentation garantiert wird. Der Rest kann funktionieren oder auch 
nicht, also keine Annahmen einfach so oder durch ausprobieren treffen.

Bei deiner Frage musst du aber noch zwischen Bibliothek und 
Betriebssystem unterscheiden. Bei z.B. C++, boost oder Qt sollte es bis 
auf die Pfadsyntax unabhängig vom Betriebssystem sein. Wenn du jetzt 
Win32 direkt verwendest, dann gilt das was Windows dort vorgibt.

Gerade in den Details, die für dich ja relevant sind, unterscheiden sich 
die verschiedenen Libs aber durchaus. Deshalb wirst du wahrscheinlich 
kein allgemeines Kompendium finden, wenn du dich nicht auf eine 
Bibliothek einschränkst.

von asd (Gast)


Lesenswert?

> Prinzipiell kann man sich dann nur auf das verlassen, was in
> der Dokumentation garantiert wird.

Das ist klar. Diese Beschreibungen sind mir aber oft zu abstrakt, bzw. 
ohne die nötige "Griffigkeit" in der Praxisrelevanz.
Z.B. kam die Frage auf, wenn fopen einen nicht-NULL-Pointer als File 
Handler zurück liefert, ist dann alles ok? Oder gibt es doch 
Spezialfälle in denen man noch weiteres beachten muss? Z.B. könnte was 
in der Zeit passieren zwischen dem Aufruf von fopen und fclose. 
Zugriffsrechte werden verändert, das Netzwerk zum Samba-Share hat einen 
hänger, was auch immer. Vielleicht ist das egal, fclose fängt da ab. 
Vielleicht gibt es einen Spezialfall in dem man als Programmierer 
beachten. Die reine Beschreibung der lib gibt das nicht her (zumindest 
nicht so dass ich mir sicher bin dass ich es verstanden habe)
Kann man einfach fclose aufrufen wenn man einen nicht-NULL-Pointer von 
fopen bekommen hat (Konkretes Problem: In ganz seltenen Fällen crasht 
das Programm beim fclose, und keiner weiß warum. Theorie: Die 
Fehler-Abfang-Logik beachtet einen Sonderfall nicht)
Außerdem können beim Kunden exotische Konfigurationen auftreten die 
keiner vorhersehen kann.
Da wäre ein Kompendium nicht schlecht das einen durch einen konkreten 
Fall führt und z.B. ein Kapitel darüber hat was die Best Practises sind 
beim Files auf- und zu machen. Und zwar nicht nur den einfachen Fall, 
sondern auch für die praxisrelevanten Sonderfälle.
Klar, dazu braucht es einen Autor der Ahnung hat, und davon gibt es 
nicht viele.
Natürlich kann so ein Buch nicht alle libs abdecken, aber wenn die 
üblichen  libs abgedeckt werden sind die bei Visual C++ dabei sind, wäre 
das ein Anfang. Und vielleicht wird man in dem Buch ja auf andere 
Methoden und libs hingewiesen die für manche Anwendungen besser sind.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

asd schrieb:
> fopen einen nicht-NULL-Pointer als File Handler zurück liefert,

Das ist kein "Handler", sondern ein "Handle". Ein "Handler" ist eine 
Funktion o.ä., die etwas behandelt, ein "Handle" ist ein "Griff", ein 
Ding, womit man etwas "anfassen" oder "manipulieren" kann, wie eben 
Deine Datei.


Wenn Du davon ausgehst, daß die Netzwerkverbindung sehr instabil ist, 
dann musst Du vor jeder Dateioperation die Gültigkeit der hinter dem 
Handle steckenden Verwaltungsinformationen prüfen.

Die Funktionen der Standardlibrary gehen nicht von derartig kaputten 
Umgebungen aus, Du wirst also mit den unterliegenden 
Betriebssystemfunktionen hantieren müssen, wenn Du jeweils den 
tatsächlichen Status der Dateiverwaltungsinformation prüfen willst. Da 
da aber einiges an Caching dazwischen liegen dürfte, wird das noch nicht 
mal besonders einfach.

In so einer Situation ist es am sinnvollsten, die Datei nur solange 
jeweils geöffnet zu haben, wie tatsächlich auf Inhalte zugegriffen wird, 
und sie sofort danach wieder zu schließen.

von mh (Gast)


Lesenswert?

Rufus Τ. F. schrieb:
> Wenn Du davon ausgehst, daß die Netzwerkverbindung sehr instabil ist,
> dann musst Du vor jeder Dateioperation die Gültigkeit der hinter dem
> Handle steckenden Verwaltungsinformationen prüfen.

Da die Probleme aber auch auftreten könnenen direkt nachdem man geprüft 
hat und bevor oder während man den Handle nutzt ist das nicht wirklich 
machbar. Das einzige was man machen kann ist "normale" Fehlerbehandlung 
zu nutzen, also Rückgabewerte von fopen/fread/ferror und wenn nötig 
errno auslesen.

asd schrieb:
> (Konkretes Problem: In ganz seltenen Fällen crasht
> das Programm beim fclose, und keiner weiß warum. Theorie: Die
> Fehler-Abfang-Logik beachtet einen Sonderfall nicht)
Dann solltet ihr die Doku nochmal lesen und sicher stellen, dass eure 
Fehler-Abfang-Logik korrekt ist.

von Hans-Georg L. (h-g-l)


Lesenswert?

Ein Handle ist eine dynamische Zugriffsnummer auf eine Systemresource 
und kann vom System wieder verwendet werden. Solange das Handle als 
invalid markiert ist bekommst du beim close INVALID_HANDLE zurück. Wenn 
das System das Handle jedoch schon recycled hat kann es wieder gültig 
sein und du schliesst ein anderes Systemobjekt.
Vermutung: Irgend jemand schliesst dein Handle und du greifst nach einer 
gewissen Zeit darauf zu.

von Ein Freund (Gast)


Lesenswert?

lemma 1:
Niemand kann von haus aus nach Schema-F den absolut richitgen Code 
schreiben.
lemma 2:
Jeder Code, der nicht getestet ist, funktioniert nicht.
lemma 3:
lerning by doing is a must.

Reines Programmieren perfekt lernen zu wollen ist wie Chinesisch zu 
lernen, ohne es je anzuwenden. Daraus folgt: Du wirst nie Chinesisch 
können. Du kannst auch Kochen nicht über Rezepte lernen. In 21 Tagen zum 
5-Sterne-Koch: Vergiss es!

Die Lösung deines Anspruches in Sachen Perfektion liegt in Deinem 
iterierenden Bemühen, also Deinem Fleiß und Deine Ausdauer, 
Problemstellungen erkennen, analysieren, erfassen und lösen zu können. 
Danach die Lösung zu Perfektionieren,  meint in puncto Tests, 
Sicherheit, continous integration etc., alles das, was Du jetzt eben 
nicht "sexy" findest. Aber das gehört unbedingt dazu. Perfektes 
Programmieren lernen zu wollen, ohne den Bezug zu Software Engineering 
haben zu wollen ist: infantil.

Backgroundinformation:

1. Geh in eine (Uni)Bibliothek. Verbring viel Zeit dort. Du wirst es nie 
wieder missen wollen.
a. Such Dir verschiendeste Literatur von Bjarne Stroustrup z.B. zum 
Thema "The C++ Programming Language" und anderes mehr von ihm.
b. Such Dir zum Thema Secure Programming for C and C++ Literatur, 
studier sie begleitend zu Übungen und Kommunikation mit anderen (Foren, 
Listen etc.)
c. Such Dir Literatur zu C und Richard Stallman, studier sie. Versuche 
selbst den Unterschied herauszufinden zwischen Visual C++ und C++ und C.
d. Such Dir Bücher über Praktische C++ Programmierung. Siehe O'Reilly 
Serien etc.
e. Such Dir Bücher über Effective C++ z.b. von Scott Meyers.
f. Such Dir Primers über C++ und versuche die darin enthaltenen 
Beispiele zu programmieren.
g. Such Dir Bücher generell über Software Engineering, damit Du 
Aufgabenstellungen überhaupt einmal erst richtig "behirnen" lernst.
h. Such Dir eine andere Programmiersprache aus z.B. LISP . Versuche die 
Übungen, die Du mittels C++ geschafft hast mit LISP zu lösen.
i. Verschaff Dir generell mal einen Überblick über die Art und Vielzahl 
von Programmiersprachen.
j. Lerne eine neue, weitere Programmiersprache.
k. Suche Dir Literatur über Noam Chomsky ... Generative Grammatik

Solltest Du nach dem Punkt K nicht von selbst die Punke L-Z finden, 
kannst Du Dich gerne
an mich wenden, um sie Dir aufzulisten. Ich denke aber, wenn Du bis K 
gekommen bist, erübrigt es sich. Dann bist Du auf solidem Weg in deinen 
Beruf (=kommt von berufen sein).
Den seinen gibts der Herr im Schlafe. Angeblich. Doch das trifft, wenn 
überhaupt nur auf die Wenigsten zu. Im Schweisse deines Angesichts 
sollst Du Dir Dein Brot verdienen.

Gruß

Ein Freund

von Irgendwer (Gast)


Lesenswert?

Allgemeines wird da nie alles abdecken, egal wie lange man in der 
Biblio. rumhängt oder Bücher wälzt(wobei das aber generell nicht 
verkehrt ist:-)

Ansatzpunkt würde ganz konkret bei den jeweiligen Funktionen nach 
zuschauen.
z.B.: http://www.cplusplus.com/reference/fstream/fstream/open/
Da wird auch etliches zu den "Fehlerfällen" geschrieben.
Und dazu noch die zugehörige ähnliche Beschreibung der konkret 
verwendete Funktion des verwendeten Compilers (inkl. der mitgelieferten 
Std.Bibliothek)...

von Markus F. (mfro)


Lesenswert?

Es mag individuell unterschiedlich sein, aber für mich gilt: 
Programmieren lernt man nicht aus Büchern.

Man kann (und sollte) die Grundlagen des Programmierens aus Büchern 
lernen, aber richtig Programmieren lernt man nur durch eines:


Praxis.

Anstatt also in Bibliotheken rumzuhocken, solltest Du dich vor eine 
Tastatur setzen und machen. Wenn Du das, was Du bis dahin weißt, 
wirklich beherrschst, greifst Du wieder zu einem Buch.

von S. R. (svenska)


Lesenswert?

asd schrieb:
> Das ist klar. Diese Beschreibungen sind mir aber oft zu abstrakt, bzw.
> ohne die nötige "Griffigkeit" in der Praxisrelevanz.

Das liegt daran, dass sie abstrakt genug sein müssen, um auch auf 
Anwendungsfälle anwendbar zu sein, die der Autor in diesem Momemtn nicht 
auf dem Schirm hatte.

> Z.B. kam die Frage auf, wenn fopen einen nicht-NULL-Pointer als File
> Handler zurück liefert, ist dann alles ok?

In erster Linie ist dann zumindest nichts Offensichtliches falsch (d.h. 
die Datei existiert oder kann erzeugt werden, du hast ausreichende 
Rechte, usw.)

> Oder gibt es doch Spezialfälle in denen man noch weiteres beachten
> muss? Z.B. könnte was in der Zeit passieren zwischen dem Aufruf von
> fopen und fclose.

Unvorhergesehene Dinge können immer passieren. Im Extremfall schaltet 
jemand einen beteiligten Rechner aus. Ob deine Software damit umgehen 
können muss, hängt von deiner Anwendung ab.

Dazu kommt noch, dass Caching real existiert. Selbst, wenn ein fwrite() 
gelingt, heißt das nicht, dass die Daten auch tatsächlich in der Datei 
gelandet sind. Erst, wenn auch das fclose() erfolgreich ist, kannst du 
davon ausgehen, dass alles erledigt wurde.

Daher der Ratschlag, die Datei nur möglichst kurz offen zu halten, wenn 
die Netzwerkverbindung nicht sauber ist. Schnell ist anders, aber 
"sicher, schnell, billig" geht halt nicht alles.

> Zugriffsrechte werden verändert, das Netzwerk zum Samba-Share hat einen
> hänger, was auch immer.

Bei Netzwerkdateisystemen hängt es vom Dateisystem ab, welche 
normalerweise existierende Garantien nicht mehr gelten. Es kann gut 
sein, dass eine Datei während des Zugriffs für andere Nutzer gesperrt 
ist (Locking), aber es muss nicht so sein. Hängt auch davon ab, was 
deine Anwendung vorher angefragt hat.

Es gibt Windows-APIs für File-Locking, Record-based locking und so 
Zeugs.

> Kann man einfach fclose aufrufen wenn man einen nicht-NULL-Pointer von
> fopen bekommen hat (Konkretes Problem: In ganz seltenen Fällen crasht
> das Programm beim fclose, und keiner weiß warum. Theorie: Die
> Fehler-Abfang-Logik beachtet einen Sonderfall nicht)

Wenn du ein gültiges Handle von fopen() bekommen hast, dann kannst du es 
an fclose() übergeben.

Genaueres gibt es nur, wenn du uns über den Crash informierst.

In deinem Fall geht es nicht um irgendwelche speziellen Libs, sondern um 
die C-Standardbibliothek. Die ist nicht gerade unbekannt.

von Frank _. (fbi)


Lesenswert?

S. R. schrieb:
> Erst, wenn auch das fclose() erfolgreich ist, kannst du
> davon ausgehen, dass alles erledigt wurde.

Selbst dann nicht. Ob das OS und die Hardware ihre eventuell vorhandenen 
Writecaches dann schon weggeschrieben haben ist an der Stelle alles 
andere als sicher.

S. R. schrieb:
> Wenn du ein gültiges Handle von fopen() bekommen hast, dann kannst du es
> an fclose() übergeben.

Man kann nicht nur, man sollte sogar.

von S. R. (svenska)


Lesenswert?

Frank _. schrieb:
> Selbst dann nicht. Ob das OS und die Hardware ihre eventuell vorhandenen
> Writecaches dann schon weggeschrieben haben ist an der Stelle alles
> andere als sicher.

Stimmt, ein fclose() garantiert nur ein fflush(), aber kein fsync(). 
Hätte ich jetzt ehrlich gesagt nicht erwartet.

Also vorher unbedingt noch ein fsync() nachschieben, wenn die Daten 
garantiert lesbar sein müssen - bessere Garantien gibt dann aber 
tatsächlich nicht mehr.

Frank _. schrieb:
>> Wenn du ein gültiges Handle von fopen() bekommen hast,
>> dann kannst du es an fclose() übergeben.
>
> Man kann nicht nur, man sollte sogar.

Man kann auch ein anderes Handle an fclose() übergeben oder das 
Betriebssystem das beim Programmende erledigen lassen. ;-)

Aber natürlich hast du recht. Ich meinte nur, dass ein von fopen() 
übergebenes Handle niemals von selbst ungültig wird, also immer an 
fclose() übergeben werden kann.

von Markus F. (mfro)


Lesenswert?

S. R. schrieb:
> Stimmt, ein fclose() garantiert nur ein fflush(), aber kein fsync().
> Hätte ich jetzt ehrlich gesagt nicht erwartet.
>
> Also vorher unbedingt noch ein fsync() nachschieben, wenn die Daten
> garantiert lesbar sein müssen - bessere Garantien gibt dann aber
> tatsächlich nicht mehr.

Das halte ich nur sehr bedingt für einen guten Rat.

Auf "normalen" Betriebssystemen darf man davon ausgehen, daß ein 
fclose() die Daten auch irgendwann mal zuverlässig auf die Platte 
bringt.

Wenn jetzt alle glauben, ihre Programme seien wichtiger als andere, 
anfangen, ihren Disk-Caches zu mißtrauen und fsync()en, können die 
Betriebssystemhersteller die Caches auch gleich weglassen.

Im Übrigen garantiert ein fsync() auf den Filedeskriptor einer offenen 
Datei lediglich, daß die Datei-Daten auf der Platte gelandet sind.
Für den entsprechenden Directory-Eintrag gilt das nicht. Es kann also 
immer noch passieren, daß zwar die Daten da sind wo sie hingehören, aber 
der Verzeichniseintrag eben nicht (und die Datei damit auch kaputt ist).

Wenn man's ganz wasserdicht haben will, muß man (mit einem 
entsprechenden Descriptor) das Verzeichnis ebenso fsyncen.

von Markus F. (mfro)


Lesenswert?

asd schrieb:
> Konkretes Problem: In ganz seltenen Fällen crasht
> das Programm beim fclose, und keiner weiß warum.

Hierbei dürfte es sich ziemlich sicher schlicht um einen (Programmier-) 
Fehler beim Umgang mit dynamisch allokiertem Speicher bzw. einen 
einfachen "Überschreiber" handeln.

fclose() ruft intern (u.a.) fflush() und free() auf. Wenn Ihr's 
irgendwie geschafft habt (z.B. durch ein free() von Speicher, der nicht 
dynamisch allokiert wurde oder durch Überschreiben von Speicher, der 
Euch nicht gehört) diese Pufferaddressen zu verbiegen, kann es zu 
solchen sporadischen Abstürzen kommen.

Ich würde mich an deiner Stelle mit valgrind (oder einem anderen 
Programm, das solche Fehler aufdecken kann) daran machen, Euer Programm 
kritisch zu untersuchen.

von Arc N. (arc)


Lesenswert?

S. R. schrieb:

> Dazu kommt noch, dass Caching real existiert. Selbst, wenn ein fwrite()
> gelingt, heißt das nicht, dass die Daten auch tatsächlich in der Datei
> gelandet sind. Erst, wenn auch das fclose() erfolgreich ist, kannst du
> davon ausgehen, dass alles erledigt wurde.

Gerade das ist bei fclose NICHT der Fall. Nur was in der C-Lib u.U. noch 
gebuffert ist, sollte dann dem OS übergeben worden sein.
Was das OS/die Treiber/die Hardware dann noch machen ist eine andere 
Geschichte (unter Linux reicht sync/fsync u.U. nicht 1))

1) bspw. btrfs "Btrfs does not force all dirty data to disk on every 
fsync or O_SYNC operation, fsync is designed to be fast." 
https://btrfs.wiki.kernel.org/index.php/FAQ#Does_Btrfs_have_data.3Dordered_mode_like_Ext3.3F

von S. R. (svenska)


Lesenswert?

Arc N. schrieb:
> Gerade das ist bei fclose NICHT der Fall.

Das wurde mir bereits mitgeteilt und ich habe meine Aussage 
diesbezüglich bereits revidiert. Drei Posts über deinem. Lesen!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.