Guten Morgen,
ich möchte gern eine .txt-Datei in meinem C-Programm öffnen und den
Inhalt in einen String einlesen. Ich Programmiere in Visual-Studio! Der
Compiler "mag" die Funktion fopen nicht, daher nehme ich fopen_s zum
öffnen der Datei. Die Funktion gibt 0 zurück, was. soweit ich weiß,
"kein Fehler" bedeutet. Im übergebenen File-Pointer steht bei "_ptr"
aber NULL. Ich habe schon eine weile gesucht, finde aber nirgends einen
Hinweis auf meinen Fehler.
Hallo,
du könntest ja jetzt sagen was du anders gemacht hast. Das würde auch
anderen helfen die nächste Woche über das gleiche Problem stolpern und
die Suchfunktion im Forum benutzten.
Das machen zwar nicht viele, aber vielleicht hilft es ja :-)
Microsoft hat sich zwar was dabei gedacht, als sie die Warnung 4996
eingeführt haben, aber sie haben nicht weit genug oder zu weit gedacht.
Es gibt diverse Funktionen in der C-Laufzeitumgebung, die historisch
gewachsen sind und die Einfalltore für Sicherheitslücken, Speicherlecks
o.ä. sind. Den Programmierer dazu zu bewegen, diese Funktionen nicht
mehr zu nutzen, sondern auf sicherere Varianten umzusteigen, ist keine
schlechte Idee.
So ist beispielsweise strcpy ein Problem, weil es nicht die Länge des
Zielpuffers überprüfen kann.
Microsoft schlägt hier eine nur auf MS-Compilern verfügbare Funktion
strcpy_s vor, die sich nur durch die Reihenfolge der Argumente von
strncpy unterscheidet.
Der Hintergedanke ist wohl, daß immer Pointer und Mengenangabe direkt
aufeinanderfolgen sollen.
Derartige Problemzonen gibt es viele, und an vielen dieser Problemzonen
ist das auch sehr sinnvoll.
Allerdings treibt Microsoft es zu weit, indem sie auch eher
unproblematische Funktionen wie fopen und tatsächlich auch strncpy
benörgelt.
Und da wird die gut gemeinte Absicht zu Schwachsinn.
Ergo: Abschalten. Und "von Hand" darauf achten, kein strcpy o.ä. zu
verwenden.
Wenn man in C programmieren will, dann kann man freilich auch gleich
einen Compiler verwenden, der den Standard C99 unterstützt.
Damit ist MS leider raus. Hach wie schade ;)
Mark Brandis schrieb:> Damit ist MS leider raus. Hach wie schade ;)
Kann man machen. Damit verzichtet man aber auch auf so ziemlich den
besten verfügbaren Debugger.
Ich habe bislang kein überzeugendes Argument gehört, das dafür spricht,
zwingend C99 verwenden zu müssen.
(Wobei die "Argumentation" von MS, warum sie keinen C99-konformen
C-Compiler herausbringen wollen, auch an Peinlichkeit nur schwer zu
überbieten ist: Das "Argument" lautet: "Wer C99 braucht, soll doch
einfach C++ verwenden ...")
Rufus Τ. Firefly schrieb:> Allerdings treibt Microsoft es zu weit, indem sie auch eher> unproblematische Funktionen wie fopen und tatsächlich auch strncpy> benörgelt.
Der Unterschied zwischen den an sich schon sicheren C-Funktionen wie
fopen und strncpy und ihren MS-Äquivalenten liegt wohl neben dem
geänderten Aufruf ausschließlich darin, dass in den MS-Funktionen die
Pointer-Argumente auf ungleich NULL überprüft werden. Zusätzliche
Sicherheit wird dadurch aber nicht gewonnen, da die Dereferenzierung
eines Null-Pointers sowieso einen Segfault auslöst.
Mark Brandis schrieb:> Wenn man in C programmieren will, dann kann man freilich auch gleich> einen Compiler verwenden, der den Standard C99 unterstützt.
Hat sich in C99 gegenüber C90 irgendetwas geändert, was die Lösung des
hiewr diskutierten Problems erleichtern würde?
Rufus Τ. Firefly schrieb:> Ich habe bislang kein überzeugendes Argument gehört, das dafür spricht,> zwingend C99 verwenden zu müssen.
Es gibt auch keins, denn statt zu C99 kann man auch gleich zu C11
übergehen ;-)
Damit fällt MS natürlich noch etwas weiter hinter die aktuelle
Entwicklung zurück, und das Argument, stattdessen C++ zu verwenden,
greift noch weniger. Aber sei's drum: Neue Windows-Applikationen werden
sowieso nicht mehr in C programmiert, und bestehende C-Applikationen
müssen brauchen nicht den neuesten C-Standard. Somit gibt es kaum Gründe
für MS, C weiter zu unterstützen.
Rufus Τ. Firefly schrieb:> Microsoft schlägt hier eine nur auf MS-Compilern verfügbare Funktion> strcpy_s vor, die sich nur durch die Reihenfolge der Argumente von> strncpy unterscheidet.
Open Watcom kennt die auch ...
Hallo Rufus,
Rufus Τ. Firefly schrieb:> Microsoft hat sich zwar was dabei gedacht, als sie die Warnung 4996> eingeführt haben, aber sie haben nicht weit genug oder zu weit gedacht.>> Es gibt diverse Funktionen in der C-Laufzeitumgebung, die historisch> gewachsen sind und die Einfalltore für Sicherheitslücken, Speicherlecks> o.ä. sind. Den Programmierer dazu zu bewegen, diese Funktionen nicht> mehr zu nutzen, sondern auf sicherere Varianten umzusteigen, ist keine> schlechte Idee.>> [...]>> Allerdings treibt Microsoft es zu weit, indem sie auch eher> unproblematische Funktionen wie fopen und tatsächlich auch /strncpy/> benörgelt.>> Und da wird die gut gemeinte Absicht zu Schwachsinn.
Wenn Entwickler mit der Warnung dazu gebracht werden, die
Ersatzfunktionen anstatt der standardisierten Originale zu benutzen, ist
der Quellcode nicht mehr portabel und die Wettbewerber ausgesperrt...
Wenn man sich dann einmal anschaut, wie Microsoft sich seines
Wettbewerbers DR-DOS entledigt hat
(http://en.wikipedia.org/wiki/AARD_code) werden unschöne Erinnerungen an
diese und andere FUD-Strategien wach, etwa bei Java.
Liebe Grüße,
Karl
Karl Käfer schrieb:> Wenn Entwickler mit der Warnung dazu gebracht werden, die> Ersatzfunktionen anstatt der standardisierten Originale zu benutzen ...
Eben. Es hätte völlig gereicht, bei strcpy, gets und der ganzen
lausigen scanf -Familie eine Warnung auszugeben und in der
Dokumentation auf die Varianten mit Mengenangabe zu verweisen, statt
redundante Funktionen mit anderen Namen und inkompatiblem Aufruf zu
erfinden.
Naja, mit dem o.g. Pragma oder der korrespondierenden
Compilereinstellung ist das Thema ja aus der Welt zu schaffen.
Rufus Τ. Firefly schrieb:> Microsoft schlägt hier eine nur auf MS-Compilern verfügbare Funktion> strcpy_s vor, die sich nur durch die Reihenfolge der Argumente von> strncpy unterscheidet.
strcpy_s hängt auf alle Fälle eine '\0' ans Ende
strncopy macht dies nicht, wenn der Quellstring >= der angegebenen
Anzahl ist.
Auch strncat und strcat_s verhalten sich unterschiedlich.
Was spricht dagegen, das Verhalten von strncpy und strncat zu
ändern?
In den mittlerweile 25 Jahren, die ich mein Geld mit C verdiene, habe
ich dieses spezifische "Feature" nie benötigt, noch ist mir ein Fall
untergekommen, wo es hätte sinnvoll sein können.
Rufus Τ. Firefly schrieb:> Microsoft schlägt hier eine nur auf MS-Compilern verfügbare Funktion> strcpy_s vor, die sich nur durch die Reihenfolge der Argumente von> strncpy unterscheidet.>> Der Hintergedanke ist wohl, daß immer Pointer und Mengenangabe direkt> aufeinanderfolgen sollen.
Bei solchen Aktionen habe ich immer eher den Eindruck, daß der
Hintergedanke ist, dem Programmierer die Benutzung einer Funktion
aufzuschwatzen, die zum Rest der Welt inkompatibel ist.
Rufus Τ. Firefly schrieb:> Ich habe bislang kein überzeugendes Argument gehört, das dafür spricht,> zwingend C99 verwenden zu müssen.
Zwingend verwenden muß man es nicht. Man muß ja auch nicht zwingend C89
verwenden. Es gibt ja auch noch K&R C. Es stellt sich nicht die Frage,
ob zwingend nötig, sondern ob es nützlich und praktisch wäre, es nutzen
zu können.
Rolf Magnus schrieb:> Es gibt ja auch noch K&R C. Es stellt sich nicht die Frage,> ob zwingend nötig, sondern ob es nützlich und praktisch wäre, es nutzen> zu können.
Das ist hart am Trollbeitrag. Der Unterschied zwischen K&R-C und C89 ist
ganz erheblich, wo aber ist C99 tatsächlich so nützlich und praktisch,
wie Du zu suggerieren scheinst?
Welches C99-spezifische Sprachfeature vereinfacht beispielsweise Dir
die Arbeit?
Rufus Τ. Firefly schrieb:> Welches C99-spezifische Sprachfeature vereinfacht beispielsweise Dir> die Arbeit?
Du hast schon recht: Der Schritt von C90 nach C99 ist ein viel kleinerer
als der von K&R nach C90. Trotzdem setzt C99 es ein paar wichtige Dinge
um, die vorher allenfalls als Spracherweierungen existierten. Die drei
wichtigsten sind aus meiner Sicht:
- Zeilenkommentare (//)
- Integer-Datentypen mit vorgegebener (Mindest-)Bitbreite
- Die neuen Funktionen snprintf und vsnprintf
Zudem erlaubt C99 endlich einen einheitlichen Umgang mit booleschen
Werten (der allerdings oft im Konflikt mit bestehendem C-Code steht).
Der eine oder andere Physiker oder Elektroingenieur mag sich sicher auch
am Datentyp complex erfreuen.
Auch die "Compound Literals" sind mitunter ganz praktisch.
Yalu X. schrieb:> Die drei wichtigsten sind aus meiner Sicht:>> - Zeilenkommentare (//)>> - Integer-Datentypen mit vorgegebener (Mindest-)Bitbreite>> - Die neuen Funktionen snprintf und vsnprintf
Nun, die drei Punkte erfüllt auch der nicht-C99-konforme
Microsoft-C-Compiler der in VS2010 enthalten ist.
Wenn auch mit der kleinen Einschränkung, daß snprintf nur mit
vorangestelltem Unterstrich verfügbar ist.
Bis auf stdint.h sind das Features, die ich schon zu Zeiten von VC 6
genutzt habe ... und lange davor; der Zeilenkommentar wird wohl schon
sehr lange toleriert.
Habe mal in alten Sourcen gegraben, und ein 20 jahre altes C-File
gefunden, in dem ich auch schon Zeilenkommentare genutzt habe. Das war
damals der mit dem Win32-SDK ausgelieferte Microsoft-C-Compiler, genaue
Versionsnummer habe ich jetzt nicht parat. _snprintf gab es damals auch
schon.
Seit wann Microsoft stdint.h (in ernstgemeint) kennt, muss ich zu meiner
Schande gestehen, nicht zu wissen.
Yalu X. schrieb:> Somit gibt es kaum Gründe für MS, C weiter zu unterstützen.
Siehe da, zumindest ein bisschen bewegen sie sich doch:
http://arstechnica.com/information-technology/2013/06/c99-acknowledged-at-last-as-microsoft-lays-out-its-path-to-c14/
Zitat:
"The final version of 2013 will also include a few C99 features.
Microsoft has long avoided supporting C99, the major update to C++'s
predecessor that was standardized last millennium, claiming that there
was little demand for it among Visual Studio users. This was true, but
only to a point; it's true that many Windows developers weren't
especially interested in C99 because they had no good tooling to support
it. Open source developers, however, embraced the update, as it makes C
a lot less awkward to work with.
While full C99 support is still not in the cards, Sutter said that
certain specific features were going to be added, including C99's
compound literals and direct initializers. These additions will mean
that many open source projects will become buildable in Visual Studio
without demanding significant code changes. Sutter mentioned widely used
video codec library ffmpeg as a specific example of a project that would
work given these compiler improvements."
Rufus Τ. Firefly schrieb:> Nun, die drei Punkte erfüllt auch der nicht-C99-konforme> Microsoft-C-Compiler der in VS2010 enthalten ist.
Das ist ja super, dann liegt MS ja doch nicht so weit abseits, wie alle
immer denken :)
> Bis auf stdint.h sind das Features, die ich schon zu Zeiten von VC 6> genutzt habe ... und lange davor; der Zeilenkommentar wird wohl schon> sehr lange toleriert.
Klar, natürlich sind viele der C99-Features schon vor der offiziellen
Veröffentlichung des Standards implementiert worden, aber da waren es
eben noch Spracherweiterungen, die streng genommen nicht standardkonform
waren.
Auch die Funktionsprototypen – eines der zentralen Features des
ANSI-C-Standards von 1989 – gab es schon in der ersten GCC-Version
(0.9), die schon zwei Jahre früher erschien (natürlich wussten die
GCC-Entwickler aus Vorveröffentlichungen schon, wie der Standard in etwa
aussehen würde).
Mit der gleichen Begründung, mit der man C99 ablehnt, könnte man auch
ANSI-C bzw. C90 ablehnen, da man ja auch mit entsprechend erweiterten
K&R-Compilern (wie dem Ur-GCC) in den Genuss der wesentlichen
C90-Features kommt.
Generell nutze ich nicht standardisierte Spracherweiterungen, wenn
überhaupt, nur in privaten Hobbyprojekten..
Wenn aber ein Auftraggeber (Chef oder Kunde) von mir ANSI-C oder C90
verlangt, dann erfülle ich seinen Wunsch konsequent und verwende bspw.
keine Zeilenkommentare. Man geht damit von vorneherein potentiellen
Scherereien aus dem Weg. So hatte bei einem Kunden aus der Autobranche,
der auf ANSI-C bestand, der Code-Checker neben vielen anderen Dingen
richtigerweise auch Zeilenkommentare rigoros zurückgewiesen (die von der
Firma eingesetzten C-Compiler wären übrigens C99-konform gewesen).
Hat der Auftraggeber bezüglich des C-Standards hingegen keine Präferenz
und will einfach nur C, dann halte ich mich selbstverständlich an den
aktuellsten Standard (derzeit C11), da mit dem Erscheinen einer neuen
Ausgabe die bisherigen Ausgaben offiziell ungültig werden. Trotzdem
setze ich die neuen Features mit Bedacht ein, um ggf. eine Portierung
auf nicht ganz aktuelle Compiler nicht unnötig zu erschweren.
Nur auf den MS-C-Compiler, der mutwilligerweise auf den Stand vor einem
Vierteljahrhundert eingefroren worden ist, nehme ich keine Rücksicht :D
was ist bei Embedded-Projekten zum Glück auch nicht nötig ist. Aber da
nach dem von Mark verlinkten Artikel MS inzwischen gewillt zu sein
scheint, wenigstens ein paar der verschlafenen jahre wieder aufzuholen,
wird am Ende sowieso alles gut :)
Was ich in diesem Zusammenhang ganz witzig finde:
Das Kommentarsymbol // stammt ursprünglich gar nicht von C++, sondern
von BCPL aus dem Jahre 1966, einem Vorläufer von C. Die B- und
C-Entwickler entschieden sich aber für das mehrzeilige /* ... */ aus
PL/I. Erst nach einer viele Jahre dauernden Odysse über C++ und Java ist
das // schließlich auch offiziell in C angekommen :)
Yalu X. schrieb:> Wenn aber ein Auftraggeber (Chef oder Kunde) von mir ANSI-C oder C90> verlangt, dann erfülle ich seinen Wunsch konsequent und verwende bspw.> keine Zeilenkommentare. Man geht damit von vorneherein potentiellen> Scherereien aus dem Weg. So hatte bei einem Kunden aus der Autobranche,> der auf ANSI-C bestand, der Code-Checker neben vielen anderen Dingen> richtigerweise auch Zeilenkommentare rigoros zurückgewiesen (die von der> Firma eingesetzten C-Compiler wären übrigens C99-konform gewesen).
Versteh ich jetzt nicht. C99 ist doch auch ANSI-C. Oder?
Und wo ist das Problem? Wenn der Code-Checker nach C99 Standard prüft,
sind // Kommentare selbstverständlich in Ordnung. Oder
Variablendeklarationen, die nicht direkt am Anfang einer Funktion
stehen.
Mark Brandis schrieb:> Oder Variablendeklarationen, die nicht direkt am Anfang> einer Funktion stehen.
Präziser: Am Anfang eines Blockes.
Und da scheiden sich die Geister - das mag der C-Compiler von Microsoft
(in VC2010 und älter) nicht.
Also:
1
intbla(intfusel)
2
{
3
intx;
4
5
x=machwas();
6
7
inty;// *1*
8
9
for(inti=0;i<7;i++)
10
{
11
intz;// *2*
12
13
//...
14
}
15
}
Fall 1 wird von nicht-C99-konformen C-Compilern angekreidet, Fall 2 ist
jedoch bereits mit C89 legal gewesen.
Nun gibt es verschiedene Ansichten darüber, ob diese Art der
Variablendefinition wünschenswert ist.
Manche meinen, daß Variablen frühestens dort definiert werden sollen, wo
sie das erste mal verwendet werden, eine andere Sichtweise ist es, alle
Variablen innerhalb eines Blocks an dessen Anfang zu definieren, um
einen Überblick darüber zu haben, welche denn überhaupt definiert
werden.
Hängt man der einen Sichtweise an, stört einen das Fehlen dieses
Features (der Variablendefinition nicht nur am Blockanfang) nicht, sieht
man das anders, musste man bis C99 mit C++ vorlieb nehmen.
Mark Brandis schrieb:> Versteh ich jetzt nicht. C99 ist doch auch ANSI-C. Oder?
Nein. Der ANSI-C-Standard ist von 1989 und wurde nacheinander durch die
ISO-C-Standards von 1990 (mit Ergänzungen von 1994), 1999 und 2011
abgelöst.
Die in diesen vier Standards beschriebenen C-Spezifikationen werden oft
kurz als C89, C90, C99 und C11 bezeichnet. Dabei unterscheidet sich C90
(ISO) nur marginal von C89 (ANSI), weswegen die Bezeichnungen "ANSI-C",
"C89" und "C90" oft synonym verwendet werden.
Mark Brandis schrieb:> Und wo ist das Problem? Wenn der Code-Checker nach C99 Standard prüft,> sind // Kommentare selbstverständlich in Ordnung.
Der Code-Checker hat aber nach ANSI bzw. C89 geprüft, weil firmeninterne
Programmierrichtlinien diesen (alten) Standard vorgaben. Deswegen durfte
man keine //-Kommentare benutzen, obwohl sie der verwendete Compiler
ohne jegliche Warnungen akzeptiert hat.
Ich wollte mit dem Beispiel in Reaktion auf Rufus' Beitrag
Rufus Τ. Firefly schrieb:> Habe mal in alten Sourcen gegraben, und ein 20 jahre altes C-File> gefunden, in dem ich auch schon Zeilenkommentare genutzt habe.
nur ausdrücken, dass man vorsichtig sein sollte, irgendwelche
Sprachfeatures zu benutzen, die zwar von praktisch allen Compilern
akzeptiert werden, aber nicht offiziell standardisiert sind.
Natürlich ist die Verwendung der //-Kommentare in ANSI-C-Programmen auch
kein großes Missgeschick, da sie ggf. auch nachträglich noch ohne großen
Aufwand in /**/-Kommentare konvertiert werden können.