Discussion:
UTF-8 mit Shell konvertieren
(zu alt für eine Antwort)
Thomas Koenig
2016-11-07 08:29:09 UTC
Permalink
Raw Message
[x-post, F'up nach de.comp.lang.c]
Im Linux Umfeld weigert man sich z.B. immer noch die strl*()
Funktionen in libc zu integrieren obwohl es keine bessere Methode gibt mit
begrenztem String-Speichern umzugehen.
Wer oder was sind die strl* - Funktionen?
Martin Vaeth
2016-11-07 08:53:56 UTC
Permalink
Raw Message
Post by Thomas Koenig
[x-post, F'up nach de.comp.lang.c]
Im Linux Umfeld weigert man sich z.B. immer noch die strl*()
Funktionen in libc zu integrieren obwohl es keine bessere Methode gibt mit
begrenztem String-Speichern umzugehen.
Wer oder was sind die strl* - Funktionen?
https://www.freebsd.org/cgi/man.cgi?query=strlcpy&sektion=3
Thomas Koenig
2016-11-07 09:09:26 UTC
Permalink
Raw Message
Post by Martin Vaeth
Post by Thomas Koenig
[x-post, F'up nach de.comp.lang.c]
Im Linux Umfeld weigert man sich z.B. immer noch die strl*()
Funktionen in libc zu integrieren obwohl es keine bessere Methode gibt mit
begrenztem String-Speichern umzugehen.
Wer oder was sind die strl* - Funktionen?
https://www.freebsd.org/cgi/man.cgi?query=strlcpy&sektion=3
Ah, IC. Scheint durchaus eine sinnvolle Ergänzung zu sein,
wobei sie in POSIX oder der C-Norm nicht dabei ist.

Sinnvolle Ergänzungen zu C gibt es ja eine ganze Menge,
was die Portabilität von Programmen nicht unbedingt erhöht.
Einige schaffen es dann auch in die nächste Norm, andere nicht.
Helmut Schellong
2016-11-07 14:01:32 UTC
Permalink
Raw Message
On 11/07/2016 10:09, Thomas Koenig wrote:
[...]
Post by Thomas Koenig
Post by Martin Vaeth
Post by Thomas Koenig
Wer oder was sind die strl* - Funktionen?
https://www.freebsd.org/cgi/man.cgi?query=strlcpy&sektion=3
Ah, IC. Scheint durchaus eine sinnvolle Ergänzung zu sein,
wobei sie in POSIX oder der C-Norm nicht dabei ist.
Sobald eine Funktion, die die zulässige Datenmenge im Zielpuffer
überwacht, aktiv begrenzen muß, ist eine Situation erreicht,
die nicht akzeptiert werden kann, auch nicht, wenn eine
terminierende \0 garantiert wird.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Thomas Koenig
2016-11-07 14:09:05 UTC
Permalink
Raw Message
Post by Helmut Schellong
[...]
Post by Thomas Koenig
Post by Martin Vaeth
Post by Thomas Koenig
Wer oder was sind die strl* - Funktionen?
https://www.freebsd.org/cgi/man.cgi?query=strlcpy&sektion=3
Ah, IC. Scheint durchaus eine sinnvolle Ergänzung zu sein,
wobei sie in POSIX oder der C-Norm nicht dabei ist.
Sobald eine Funktion, die die zulässige Datenmenge im Zielpuffer
überwacht, aktiv begrenzen muß, ist eine Situation erreicht,
die nicht akzeptiert werden kann, auch nicht, wenn eine
terminierende \0 garantiert wird.
Der, der den Pfahl, der am Weg, der nach Worms führt, steht, liegt,
umgeworfen hat, zahlt zwei Mark und fließt in die Gemeindekasse?
Helmut Schellong
2016-11-07 14:40:05 UTC
Permalink
Raw Message
Post by Thomas Koenig
Post by Helmut Schellong
[...]
Post by Thomas Koenig
Post by Martin Vaeth
Post by Thomas Koenig
Wer oder was sind die strl* - Funktionen?
https://www.freebsd.org/cgi/man.cgi?query=strlcpy&sektion=3
Ah, IC. Scheint durchaus eine sinnvolle Ergänzung zu sein,
wobei sie in POSIX oder der C-Norm nicht dabei ist.
Sobald eine Funktion, die die zulässige Datenmenge im Zielpuffer
überwacht, aktiv begrenzen muß, ist eine Situation erreicht,
die nicht akzeptiert werden kann, auch nicht, wenn eine
terminierende \0 garantiert wird.
Der, der den Pfahl, der am Weg, der nach Worms führt, steht, liegt,
umgeworfen hat, zahlt zwei Mark und fließt in die Gemeindekasse?
In fast allen solchen Fällen sollte eine Software nicht
einfach weitermachen, auch nicht n-fach.
Beispielsweise, wenn Pfadnamen kopiert oder zusammengebaut werden,
dürfen diese unter keinen Umständen gekappt irgendwohin gelangen.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Thomas Koenig
2016-11-07 14:48:13 UTC
Permalink
Raw Message
Post by Helmut Schellong
In fast allen solchen Fällen sollte eine Software nicht
einfach weitermachen, auch nicht n-fach.
Beispielsweise, wenn Pfadnamen kopiert oder zusammengebaut werden,
dürfen diese unter keinen Umständen gekappt irgendwohin gelangen.
Durchaus korrekt. Dafür ist strlcat ja auch gerade gedacht, wenn ich
das richtig sehe. Aus der Manpage:

char *dir, *file, pname[PATH_MAX];

...

if (strlcpy(pname, dir, sizeof(pname)) >= sizeof(pname))
goto toolong;
if (strlcat(pname, file, sizeof(pname)) >= sizeof(pname))
goto toolong;
Rainer Weikusat
2016-11-07 15:57:09 UTC
Permalink
Raw Message
Post by Thomas Koenig
Post by Helmut Schellong
In fast allen solchen Fällen sollte eine Software nicht
einfach weitermachen, auch nicht n-fach.
Beispielsweise, wenn Pfadnamen kopiert oder zusammengebaut werden,
dürfen diese unter keinen Umständen gekappt irgendwohin gelangen.
Durchaus korrekt. Dafür ist strlcat ja auch gerade gedacht, wenn ich
char *dir, *file, pname[PATH_MAX];
...
if (strlcpy(pname, dir, sizeof(pname)) >= sizeof(pname))
goto toolong;
if (strlcat(pname, file, sizeof(pname)) >= sizeof(pname))
goto toolong;
toolong:
fputs("Can't be arsed to do proper with string handling. Enjoy your failure!\n", stderr);
Thomas Koenig
2016-11-07 17:27:44 UTC
Permalink
Raw Message
Post by Rainer Weikusat
Post by Thomas Koenig
Post by Helmut Schellong
In fast allen solchen Fällen sollte eine Software nicht
einfach weitermachen, auch nicht n-fach.
Beispielsweise, wenn Pfadnamen kopiert oder zusammengebaut werden,
dürfen diese unter keinen Umständen gekappt irgendwohin gelangen.
Durchaus korrekt. Dafür ist strlcat ja auch gerade gedacht, wenn ich
char *dir, *file, pname[PATH_MAX];
...
if (strlcpy(pname, dir, sizeof(pname)) >= sizeof(pname))
goto toolong;
if (strlcat(pname, file, sizeof(pname)) >= sizeof(pname))
goto toolong;
fputs("Can't be arsed to do proper with string handling. Enjoy your failure!\n", stderr);
Tja... wenn jemand einen Pfadnamen zusamenstoppeln will, der länger ist als
das, was das System maximal zulässt, kann man auch mit dem besten
Stringhandling Welt nicht viel daran machen.
Rainer Weikusat
2016-11-07 17:35:51 UTC
Permalink
Raw Message
Post by Thomas Koenig
Post by Rainer Weikusat
Post by Thomas Koenig
Post by Helmut Schellong
In fast allen solchen Fällen sollte eine Software nicht
einfach weitermachen, auch nicht n-fach.
Beispielsweise, wenn Pfadnamen kopiert oder zusammengebaut werden,
dürfen diese unter keinen Umständen gekappt irgendwohin gelangen.
Durchaus korrekt. Dafür ist strlcat ja auch gerade gedacht, wenn ich
char *dir, *file, pname[PATH_MAX];
...
if (strlcpy(pname, dir, sizeof(pname)) >= sizeof(pname))
goto toolong;
if (strlcat(pname, file, sizeof(pname)) >= sizeof(pname))
goto toolong;
fputs("Can't be arsed to do proper with string handling. Enjoy your failure!\n", stderr);
Tja... wenn jemand einen Pfadnamen zusamenstoppeln will, der länger
ist als das, was das System maximal zulässt, kann man auch mit dem
besten Stringhandling Welt nicht viel daran machen.
PATH_MAX ist maximale Laenge eines Pfadnames, den eine Systemfunktion
zurueckgeben darf ausser sie uebernimmt einen Puffer mit
Laengenargument. In diesem Fall duerfen laengere Pfadnamen
zurueckgegeben werden.

Mit der maximalen Laenge eines Pfadnames fuer irgendein Dateisystem,
insofern ein solche ueberhaupt existiert, hat das leider nichts zu tun.
Claus Reibenstein
2016-11-07 09:33:22 UTC
Permalink
Raw Message
Post by Martin Vaeth
Post by Thomas Koenig
Wer oder was sind die strl* - Funktionen?
https://www.freebsd.org/cgi/man.cgi?query=strlcpy&sektion=3
Dafür gibt es die strn*-Funktionen, mit deren Hilfe man sich die
benötigten strl*-Funktionen einfach selber bauen kann.

Beispiel strlcpy:

#include <string.h>
char *strlcpy(char *s1, const char *s2, size_t n) {
strncpy(s1, s2, n - 1);
s1[n - 1] = 0;
return s1;
}

Wer bei derart Primitivem nach Implementierung in die C-Library schreit,
sollte sich überlegen, ob er nicht doch besser etwas Anderes machen
sollte, als ausgerechnet Software zu entwickeln.

Gruß
Claus
Thomas Koenig
2016-11-07 10:46:48 UTC
Permalink
Raw Message
Post by Claus Reibenstein
Post by Martin Vaeth
Post by Thomas Koenig
Wer oder was sind die strl* - Funktionen?
https://www.freebsd.org/cgi/man.cgi?query=strlcpy&sektion=3
Dafür gibt es die strn*-Funktionen, mit deren Hilfe man sich die
benötigten strl*-Funktionen einfach selber bauen kann.
#include <string.h>
char *strlcpy(char *s1, const char *s2, size_t n) {
strncpy(s1, s2, n - 1);
s1[n - 1] = 0;
return s1;
}
strlcpy scheint die Zahl der Bytes zurückzugeben, daher
müsste man an deiner Funktion noch was ändern.
Post by Claus Reibenstein
Wer bei derart Primitivem nach Implementierung in die C-Library schreit,
sollte sich überlegen, ob er nicht doch besser etwas Anderes machen
sollte, als ausgerechnet Software zu entwickeln.
Das über viele der C-Stringfunktionen sagen, die meisten lassen sich
ja mit einer einfachen Schleife implementieren.

Wenn nun eine bestimmte Funktionalität immer wieder gebraucht wird,
dann ist es durchaus sinnvoll, die in eine Standardfunktion zu packen -
das erhöht beim Lesen des Codes den Wiedererkennungswert erheblich.

Ob die Schwelle bei den strl* - Funktionen nun erreicht ist, darüber
habe ich mir noch keine Meinung gebildet. Ich habe ja erst heute
erfahren, dass es sie gibt :-)
Claus Reibenstein
2016-11-07 11:38:14 UTC
Permalink
Raw Message
Post by Thomas Koenig
Post by Claus Reibenstein
#include <string.h>
char *strlcpy(char *s1, const char *s2, size_t n) {
strncpy(s1, s2, n - 1);
s1[n - 1] = 0;
return s1;
}
strlcpy scheint die Zahl der Bytes zurückzugeben, daher
müsste man an deiner Funktion noch was ändern.
Genauer: Die Länge des Ergebnisstring. Hatte ich übersehen. Sorry.

Nun, dann eben so:

#include <string.h>
size_t strcpy(char *s1, const char *s2, size_t n) {
strncpy(s1, s2, n - 1);
s1[n - 1] = 0;
return strlen(s1);
}

Auch nicht viel komplizierter ;-)
Post by Thomas Koenig
Post by Claus Reibenstein
Wer bei derart Primitivem nach Implementierung in die C-Library schreit,
sollte sich überlegen, ob er nicht doch besser etwas Anderes machen
sollte, als ausgerechnet Software zu entwickeln.
Das über viele der C-Stringfunktionen sagen, die meisten lassen sich
ja mit einer einfachen Schleife implementieren.
Das ist richtig. Allerdings erfolgt die tatsächliche Implementierung der
C-Funktionen nicht zwangsläufig in C.
Post by Thomas Koenig
Wenn nun eine bestimmte Funktionalität immer wieder gebraucht wird,
dann ist es durchaus sinnvoll, die in eine Standardfunktion zu packen -
das erhöht beim Lesen des Codes den Wiedererkennungswert erheblich.
Oder man baut sich seine eigene(n) Bibliothek(en).
Post by Thomas Koenig
Ob die Schwelle bei den strl* - Funktionen nun erreicht ist, darüber
habe ich mir noch keine Meinung gebildet. Ich habe ja erst heute
erfahren, dass es sie gibt :-)
Ich auch.

Gruß
Claus
Martin Vaeth
2016-11-07 12:44:06 UTC
Permalink
Raw Message
Post by Claus Reibenstein
#include <string.h>
size_t strcpy(char *s1, const char *s2, size_t n) {
strncpy(s1, s2, n - 1);
s1[n - 1] = 0;
return strlen(s1);
}
Auch nicht viel komplizierter ;-)
Aber viel langsamer. Bei langen Strings um rund den Faktor 2.
(Ggf. mehr, weil die Pointer-Arithmetik bei guter Implementierung
ebenfalls überflüssig sein dürfte, und selbst die Zuweisung sogar
nur in einem Spezialfall notwendig ist).
Vom Zusammenbrechen des Prozessorcaches bei sehr langen Strings
habe ich bis jetzt noch gar nicht gesprochen...

Das Ganze ist also bestenfalls ein Hack; keine sorgfältige
Implementierung, die man in häufigen Aufrufen benutzen möchte.
Post by Claus Reibenstein
Allerdings erfolgt die tatsächliche Implementierung der
C-Funktionen nicht zwangsläufig in C.
Eben. Deswegen wäre es sinnvoll, die (schnellere) Funktion
zur Verfügung zu haben: Bei geeigneter Implementieung ist sie
vermutlich genauso schnell und Cache-freundlich wie strncpy,
hat aber deutlichen Mehrwert in der Anwendung.
Stefan Reuther
2016-11-07 17:00:21 UTC
Permalink
Raw Message
Post by Claus Reibenstein
Post by Martin Vaeth
Post by Thomas Koenig
Wer oder was sind die strl* - Funktionen?
https://www.freebsd.org/cgi/man.cgi?query=strlcpy&sektion=3
Dafür gibt es die strn*-Funktionen, mit deren Hilfe man sich die
benötigten strl*-Funktionen einfach selber bauen kann.
#include <string.h>
char *strlcpy(char *s1, const char *s2, size_t n) {
strncpy(s1, s2, n - 1);
s1[n - 1] = 0;
return s1;
}
Das ist keine effiziente Implementierung von strlcpy, da sie immer alle
n Bytes ausnullt.
Post by Claus Reibenstein
Wer bei derart Primitivem nach Implementierung in die C-Library schreit,
sollte sich überlegen, ob er nicht doch besser etwas Anderes machen
sollte, als ausgerechnet Software zu entwickeln.
'abs()' ist auch eine völlige Trivialfunktion. Dennoch ist sie in der
libc, um Entwicklern ein gemeinsames Vokabular zu ermöglichen.

Ich würde in der Library dann allerdings doch lieber Funktionen sehen,
die mit (char*,size_t)-Pärchen arbeiten und damit effizient mit Strings
jeder Länge und eingebetteten Nullbytes umgehen zu könenn, anstatt noch
ein, zwei Wrapper um nullterminierte Strings zu bauen.


Stefan
Martin Vaeth
2016-11-08 06:56:44 UTC
Permalink
Raw Message
Post by Stefan Reuther
Ich würde in der Library dann allerdings doch lieber Funktionen sehen,
die mit (char*,size_t)-Pärchen arbeiten
Die Low-level-Funktionen dazu gibt es ja: memmove, memcpy
High-level ist für so etwas nicht sinnvoll. Da sollte man
dann lieber eine Sprache nehmen, die mehr abstrahiert, statt
dass man manuell das Implementationsdetail "Paar" verwalten
und high-level und low-level Code unleserlich mixen muss:
Für so etwas wurde C++ und dessen "std::string" erfunden.
G.B.
2016-11-08 09:44:33 UTC
Permalink
Raw Message
Post by Martin Vaeth
abstrahiert, statt
dass man manuell das Implementationsdetail "Paar" verwalten
Für so etwas wurde C++ und dessen "std::string" erfunden.
Als abstrahierend geht std::string betsimmt durch. Ob C++ aber als
leserlich durchgeht, oder vielmehr auf den belegt attraktiven Charm
der bedeutungsträchtigen, magischen ASCII-Zeichensetzungssymbolik
setzt, und aus historischen Gründen setzen muss, das scheint mir
eine von abstrahierenden Typ-Büchereien trennbare Frage zu sein.

Der Gegenwert der durch reichhaltige Syntax gestützten Apparaturen
von C++ kann sich erst als eine Verbesserung im Aufwand gegenüber
dem durch C erzeugten händischen Verfahren erweisen, wenn in
ein paar Jahren C++ legacy-Entwickler gefragt sein werden, die
wissen, wie mit "template" ohne "<>" ein überladener operator<<
für einem mit "&&" referenzierten rvalue doch mit std:: genutzt
werden kann, sofern das Projekt C++11 darf.

Sich dessen rühmen zu können erscheint dann auch nicht viel
anders, als die Bedingtheiten des endlichen Automaten im Handbuch
von strlcpy(3) auswendig gelernt zu haben und komplexe Konsistenz
mit einem Entwurfsfortschritt im Aufbau von zusammenhängenden
Bücherei-Operationen zu verwechseln.
--
"HOTDOGS ARE NOT BOOKMARKS"
Springfield Elementary teaching staff
Helmut Schellong
2016-11-08 11:54:07 UTC
Permalink
Raw Message
[... ...]
Post by G.B.
Sich dessen rühmen zu können erscheint dann auch nicht viel
anders, als die Bedingtheiten des endlichen Automaten im Handbuch
von strlcpy(3) auswendig gelernt zu haben und komplexe Konsistenz
mit einem Entwurfsfortschritt im Aufbau von zusammenhängenden
Bücherei-Operationen zu verwechseln.
Wirklich freie, unabhängige, mutige Geister gibt es höchst selten.
Viele haben sich selbst konditioniert.
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Rainer Weikusat
2016-11-08 15:20:27 UTC
Permalink
Raw Message
Post by Martin Vaeth
Post by Stefan Reuther
Ich würde in der Library dann allerdings doch lieber Funktionen sehen,
die mit (char*,size_t)-Pärchen arbeiten
Die Low-level-Funktionen dazu gibt es ja: memmove, memcpy
High-level ist für so etwas nicht sinnvoll. Da sollte man
dann lieber eine Sprache nehmen, die mehr abstrahiert, statt
dass man manuell das Implementationsdetail "Paar" verwalten
Für so etwas wurde C++ und dessen "std::string" erfunden.
Fuer soetwas wurden Sprachen erfunden, die Speicherverwaltung vollkommen
automatisch machen. Das es davon aufgrund von ideologischer Blindheit/
Bloedheit[*] praktisch keine sinnvollen Implementierungen gibt, ist ein
anderes Problem.

[*] Bis zu diesem Tage besteht 'automatische Speicherverwaltung'
groesstenteil daraus, um Hardwarebeschreankungen von IBM 704 Computer im
Rahmen der 'LISP 1'-Implementierung herumzuwuergen. Das funktioniert in
der Praxis mehr schlecht als recht aber Speicher ist so billig
heutzutage und wenn wir es einfach noch ein bisschen komplzierter
machen, wird es noch schwerer, das Problem mit reproduzierbaren test
case nachzuweisen und ... (fuenfzig Jahre spaeter) ... da stehen wir
immer noch ...
Claus Reibenstein
2016-11-08 17:55:50 UTC
Permalink
Raw Message
Post by Rainer Weikusat
Fuer soetwas wurden Sprachen erfunden, die Speicherverwaltung vollkommen
automatisch machen. Das es davon aufgrund von ideologischer Blindheit/
Bloedheit[*] praktisch keine sinnvollen Implementierungen gibt, ist ein
anderes Problem.
Was genau gefällt Dir denn an der Speicherverwaltung von Java nicht?

Gruß
Claus
Rainer Weikusat
2016-11-08 20:53:08 UTC
Permalink
Raw Message
Post by Claus Reibenstein
Post by Rainer Weikusat
Fuer soetwas wurden Sprachen erfunden, die Speicherverwaltung vollkommen
automatisch machen. Das es davon aufgrund von ideologischer Blindheit/
Bloedheit[*] praktisch keine sinnvollen Implementierungen gibt, ist ein
anderes Problem.
Was genau gefällt Dir denn an der Speicherverwaltung von Java nicht?
-XX:OnOutOfMemoryError="daemon /etc/init.d/jboss restart"
Peter J. Holzer
2016-11-08 23:49:16 UTC
Permalink
Raw Message
Post by Claus Reibenstein
Post by Rainer Weikusat
Fuer soetwas wurden Sprachen erfunden, die Speicherverwaltung
vollkommen automatisch machen. Das es davon aufgrund von
ideologischer Blindheit/ Bloedheit[*] praktisch keine sinnvollen
Implementierungen gibt, ist ein anderes Problem.
Was genau gefällt Dir denn an der Speicherverwaltung von Java nicht?
Das ist einfach zu beantworten: Die Annahme, dass eine Applikation eine
fixe Menge Memory zur Verfügung hat. Hier wird die Abstraktion der JVM
(= Java Virtual Machine) zu wörtlich genommen: Eine physische Maschine
hat eine fixe Menge RAM. Eine virtuelle Maschine, die eine physische
Maschine emuliert, auch. Aber eine "virtuelle Maschine", die nichts
anderes als ein Interpreter ist, sollte ihren Speicherverbrauch dem
Bedarf anpassen können. Das kann OpenJVM/Oracle JVM meines Wissens bis
heute nicht: Jede Java-Applikation wächst bis zum konfigurierten
Maximum, weil der Garbage-Collector schlicht erst dann anspringt, wenn
dieses erreicht ist.

hp
--
_ | Peter J. Holzer | Fluch der elektronischen Textverarbeitung:
|_|_) | | Man feilt solange an seinen Text um, bis
| | | ***@hjp.at | die Satzbestandteile des Satzes nicht mehr
__/ | http://www.hjp.at/ | zusammenpaßt. -- Ralph Babel
Florian Weimer
2016-11-09 19:03:45 UTC
Permalink
Raw Message
Post by Peter J. Holzer
Das ist einfach zu beantworten: Die Annahme, dass eine Applikation eine
fixe Menge Memory zur Verfügung hat. Hier wird die Abstraktion der JVM
(= Java Virtual Machine) zu wörtlich genommen: Eine physische Maschine
hat eine fixe Menge RAM. Eine virtuelle Maschine, die eine physische
Maschine emuliert, auch. Aber eine "virtuelle Maschine", die nichts
anderes als ein Interpreter ist, sollte ihren Speicherverbrauch dem
Bedarf anpassen können. Das kann OpenJVM/Oracle JVM meines Wissens bis
OpenJVM? Meinst Du OpenJDK?
Post by Peter J. Holzer
heute nicht: Jede Java-Applikation wächst bis zum konfigurierten
Maximum, weil der Garbage-Collector schlicht erst dann anspringt, wenn
dieses erreicht ist.
Nein, es wird schon vorher aufgeräumt. Man muß beim Start allerdings
die maximale Größe angeben. Mittlerweile sollte der Speicher auch
nicht mehr sofort komplett vom Betriebssystem reserviert werden (auch
wenn das i.d.R. aufgrund der Systemkonfiguration sowieso keinen
Unterschied macht).
Peter J. Holzer
2016-11-10 05:58:36 UTC
Permalink
Raw Message
Post by Florian Weimer
Post by Peter J. Holzer
Das ist einfach zu beantworten: Die Annahme, dass eine Applikation eine
fixe Menge Memory zur Verfügung hat. Hier wird die Abstraktion der JVM
(= Java Virtual Machine) zu wörtlich genommen: Eine physische Maschine
hat eine fixe Menge RAM. Eine virtuelle Maschine, die eine physische
Maschine emuliert, auch. Aber eine "virtuelle Maschine", die nichts
anderes als ein Interpreter ist, sollte ihren Speicherverbrauch dem
Bedarf anpassen können. Das kann OpenJVM/Oracle JVM meines Wissens bis
OpenJVM? Meinst Du OpenJDK?
Ja, sorry.
Post by Florian Weimer
Post by Peter J. Holzer
heute nicht: Jede Java-Applikation wächst bis zum konfigurierten
Maximum, weil der Garbage-Collector schlicht erst dann anspringt, wenn
dieses erreicht ist.
Nein, es wird schon vorher aufgeräumt.
In Wirklichkeit ist es natürlich etwas komplizierter als ich skizziert
habe. So gibt es z.B. mehrere Bereiche für Objekte unterschiedlicher
Lebensdauer und die Details haben sich auch immer wieder mal geändert.
Post by Florian Weimer
Man muß beim Start allerdings die maximale Größe angeben.
Meiner Erfahrung nach wachsen langlaufende Java-Programme (konkret:
Application Server wie Tomcat oder JBoss/Wildfly) immer recht stetig bis
zum konfigurierten Maximum an und bleiben dann dort. Der Sysadmin hat
also die Aufgabe, sich ein sinnvolles Maximum aus den Fingern zu saugen.

hp
--
_ | Peter J. Holzer | Fluch der elektronischen Textverarbeitung:
|_|_) | | Man feilt solange an seinen Text um, bis
| | | ***@hjp.at | die Satzbestandteile des Satzes nicht mehr
__/ | http://www.hjp.at/ | zusammenpaßt. -- Ralph Babel
Thomas Koenig
2016-11-10 06:23:06 UTC
Permalink
Raw Message
Post by Peter J. Holzer
Application Server wie Tomcat oder JBoss/Wildfly) immer recht stetig bis
zum konfigurierten Maximum an und bleiben dann dort. Der Sysadmin hat
also die Aufgabe, sich ein sinnvolles Maximum aus den Fingern zu saugen.
Wie damals auf IBM-Großeisen mit MVS unter JCL...

Wenn der Rechner den in der JOB-Karte angeforderten Speicher nicht
zusichern konnte, dann wurde der Job nicht gestartet.

Wenn der Job zu viel Speicher verwenden wollte, dann gab es einen ABEND
(ABnormal END).

Der Speicherbedarf ist natürlich mit Programmiersprachen, die
weder Rekursion noch dynamische Datenstrukturen zugelassen haben,
viel einfacher zu ermitteln, und die liefen typischerweise auf
den Kisten. Das Betriebssystem kannte/kennt natürlich dynamische
Speicheranforderung mit dem GETMAIN-Makro, aber dafür muss man
Assembler verwenden, wen der Rest des Programms z.B. in Fortran
77 geschrieben ist.

Die Vorhersage des Speicherbedarfs ist heute bei HPC-Systemen mit
ziemlich stark begrenztem Hauptspeicher immer noch ein Problem.
Die Nodes haben ja normalerweise auch keine Platte und keinen Swap.
G.B.
2016-11-10 12:01:25 UTC
Permalink
Raw Message
Post by Thomas Koenig
Wie damals auf IBM-Großeisen mit MVS unter JCL...
Die Vorhersage des Speicherbedarfs ist heute bei HPC-Systemen mit
ziemlich stark begrenztem Hauptspeicher immer noch ein Problem.
Die Nodes haben ja normalerweise auch keine Platte und keinen Swap.
Anders als C als und anders als alte "dynamische" Sprachen das
Problem endlichen Speichers angegangen sind, kehren neue Programmiersprachen
die Speicherverwaltung bereits beim Entwurf unter den Teppich.
Mit ein paar Argumenten aus dem Herablassungsrepertoir der
pragmatischen Programmierung. ("Einfach ... machen". "Jeder
kompetente...". "... sinnvolles Maximum". "Lass den compiler
machen...". "Den Super-GAU sollen die Rechtsanwälte ...")

Möglicherweise wegen einer akademisch verblendeten Konzept-Trennung zwischen
Programm und Betriebssystem wird das gemeinsame Problem semantisch
nicht angemessen erfasst. Wenn ich mich an COLLECT und CLEAR sowie
das Fail-"Ereigenis" in SNOBOL-4 (1969) erinnere, dann ist immerhin
schon länger bekannt und in Sprachen implementiert, dass man auch in
Sprachen mit GC auf Speicherdruck eingehen kann. Die Aufgabe sollte quer durch
die Sprache, z.B. im Typsystem, expressive Berücksichtigung finden können.
Oder in etwas neuem, wie z.B. einem aufgebohrten interrupt handler
mit Anbindung von Speichersammlungs-Regionen.

Die Sprachintegration von Speicher (also *nicht*: Funktionen und
Konventionen) erscheint als akademisch gestütze Forschungsaufgabe
viel nützlicher, als noch ein Dateisystem, das spieltheoretisch
begabte Informatiker systematisch elaborieren, bis die letzte
Festplatte zu drehen aufgehört hat.
--
"HOTDOGS ARE NOT BOOKMARKS"
Springfield Elementary teaching staff
Stefan Reuther
2016-11-09 16:42:08 UTC
Permalink
Raw Message
Post by Claus Reibenstein
Post by Rainer Weikusat
Fuer soetwas wurden Sprachen erfunden, die Speicherverwaltung vollkommen
automatisch machen. Das es davon aufgrund von ideologischer Blindheit/
Bloedheit[*] praktisch keine sinnvollen Implementierungen gibt, ist ein
anderes Problem.
Was genau gefällt Dir denn an der Speicherverwaltung von Java nicht?
Ein Hauptproblem ist ja schon die Annahme, es gäbe außer Speicher keine
andere automatisch zu verwaltenden Ressourcen.

Praktisch gibt es die aber eben doch, z.B. in Form von File Handles. Und
weil Java dem Entwickler keine Möglichkeit in die Hand gibt, File
Handles zu schließen, außer jede Benutzung von Dateien in ein
try { ... } finally { file.close(); }
einzupacken, was keiner macht, schlägt halt im Jenkins immer mal ein
Build fehl, wenn wieder jemand der Meinung war, der Java-VM etwas mehr
RAM zu geben. Lösung: RAM-Limit runterdrehen, dann läuft der GC öfter,
dann werden die vergessenen Finalizer öfter aufgerufen, dann reichen die
File Handles wieder eine Weile.


Stefan
Florian Weimer
2016-11-09 19:06:48 UTC
Permalink
Raw Message
Post by Stefan Reuther
Praktisch gibt es die aber eben doch, z.B. in Form von File Handles. Und
weil Java dem Entwickler keine Möglichkeit in die Hand gibt, File
Handles zu schließen, außer jede Benutzung von Dateien in ein
try { ... } finally { file.close(); }
einzupacken,
Es gibt seit einer ganzen Weile try-with-resources.
Post by Stefan Reuther
was keiner macht,
Das stimmt so auch nicht. Es gibt jede Menge Software, die das
notgedrungen korrekt handhabt. Nur weiß man i.d.R. nicht, ob das
wirklich für alle Abhängigkeiten gilt, die man einsetzt.
Claus Reibenstein
2016-11-09 19:51:38 UTC
Permalink
Raw Message
Post by Stefan Reuther
weil Java dem Entwickler keine Möglichkeit in die Hand gibt, File
Handles zu schließen, außer jede Benutzung von Dateien in ein
try { ... } finally { file.close(); }
einzupacken
https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
Post by Stefan Reuther
Lösung: RAM-Limit runterdrehen, dann läuft der GC öfter,
dann werden die vergessenen Finalizer öfter aufgerufen
Falls Du mit "Finalizer" die finally-Blöcke meinst: Die werden _immer_
aufgerufen, unabhängig vom GC.

Aber wir schweifen ab. Mit C hat das nichts mehr zu tun.

Gruß
Claus
Stefan Reuther
2016-11-10 16:41:44 UTC
Permalink
Raw Message
Post by Claus Reibenstein
Post by Stefan Reuther
weil Java dem Entwickler keine Möglichkeit in die Hand gibt, File
Handles zu schließen, außer jede Benutzung von Dateien in ein
try { ... } finally { file.close(); }
einzupacken
https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
Das geht, wenn ich das richtig sehe, seit Java 7, also seit 5 Jahren.
Davor haben eine Menge Leute Java gelernt, die das nicht kennen.
Zumindest seh ich diese Anweisungsform äußerst selten.

Und solche Probleme haben halt einen Hang zu "wieso, läuft doch, im
Unittest und auf meinem Test-Setup ist alles bestens".
Post by Claus Reibenstein
Post by Stefan Reuther
Lösung: RAM-Limit runterdrehen, dann läuft der GC öfter,
dann werden die vergessenen Finalizer öfter aufgerufen
Falls Du mit "Finalizer" die finally-Blöcke meinst: Die werden _immer_
aufgerufen, unabhängig vom GC.
Ich meine mit Finalizer Finalizer: die Methode namens finalize().
Post by Claus Reibenstein
Aber wir schweifen ab. Mit C hat das nichts mehr zu tun.
Nur insofern, als dass C dem Entwickler auch keine Möglichkeit gibt, bei
durchfliegende Exceptions (longjmp) mittendrin noch was zu tun :->


Stefan
Stefan Reuther
2016-11-08 16:41:44 UTC
Permalink
Raw Message
Post by Martin Vaeth
Post by Stefan Reuther
Ich würde in der Library dann allerdings doch lieber Funktionen sehen,
die mit (char*,size_t)-Pärchen arbeiten
Die Low-level-Funktionen dazu gibt es ja: memmove, memcpy
High-level ist für so etwas nicht sinnvoll. Da sollte man
dann lieber eine Sprache nehmen, die mehr abstrahiert, statt
dass man manuell das Implementationsdetail "Paar" verwalten
Für so etwas wurde C++ und dessen "std::string" erfunden.
Ich wollte eher in die Richtung, dass für das Verwalten von Pärchen aus
(char*,size_t) in C eher sowas wie structs erfunden worden.

Und statt Energie dahinein zu investieren, die X+1'te Funktionsgruppe
einzuführen, die wieder Pointer und Länge auseinanderreißt (strncpy?
strlcpy? strcpy_s?), hätte ich gerne eine, die die beieinanderhält.

Aber bei der Verwendung von Strukturen als Funktionsparameter oder
-Rückgabewerte hat die C-Bibliothek ja traditionell doch eher Hemmungen.
Und selbst wenn es sowas im Standard gäbe, ist die Verfügbarkeit neuerer
Standards doch eher mau. Also schreibt man sich halt die Y+1'te Library
(g_string_assign? stralloc_copy?).


Stefan
Patrick.Schluter
2017-02-05 18:58:34 UTC
Permalink
Raw Message
Post by Claus Reibenstein
benötigten strl*-Funktionen einfach selber bauen kann.
#include <string.h>
char *strlcpy(char *s1, const char *s2, size_t n) {
strncpy(s1, s2, n - 1);
s1[n - 1] = 0;
return s1;
}
strncpy() ist keine gute Basis für strlcpy(). strncpy() hat den großen
Nachteil den Puffer immer bis zum Anschlag mit Nullen vollzuschreiben.
Wenn dieser sehr gross ist kann dass schon ganz schön teuer sein.
Hier ein simple Version

size_t strlcpy(char *dst, const char *src, size_t dstsize)
{
size_t len = strlen(src);
if(dstsize)
*((char*)mempcpy(dst, src, min(len, dstsize-1))) = 0;
return len;
}

Diese Version hat auch den Vorteil Ulrich Drepper's "Argument" gegen
strlcpy() in glibc ad absurdum zu führen.

schlupa
Rainer Weikusat
2017-02-05 20:59:47 UTC
Permalink
Raw Message
Post by Patrick.Schluter
Post by Claus Reibenstein
benötigten strl*-Funktionen einfach selber bauen kann.
#include <string.h>
char *strlcpy(char *s1, const char *s2, size_t n) {
strncpy(s1, s2, n - 1);
s1[n - 1] = 0;
return s1;
}
strncpy() ist keine gute Basis für strlcpy(). strncpy() hat den großen
Nachteil den Puffer immer bis zum Anschlag mit Nullen
vollzuschreiben. Wenn dieser sehr gross ist kann dass schon ganz schön
teuer sein.
Hier ein simple Version
size_t strlcpy(char *dst, const char *src, size_t dstsize)
{
size_t len = strlen(src);
if(dstsize)
*((char*)mempcpy(dst, src, min(len, dstsize-1))) = 0;
return len;
}
Diese Version hat auch den Vorteil Ulrich Drepper's "Argument" gegen
strlcpy() in glibc ad absurdum zu führen.
Motto "If you can't dazzle them with brilliance, baffle them with
bullshit". Der referenzierte Text war

This is horribly inefficient BSD crap. Using these function only
leads to other errors. Correct string handling means that you always
know how long your strings are and therefore you can you memcpy
(instead of strcpy).

http://www.sourceware.org/ml/libc-alpha/2000-08/msg00053.html

Daraus, dass die oa Funktion die Stringlaenge durch Zeichenzaehlen
ermitteln muss, kann man entnehmen, dass diese Stringlaenge nicht (wie
von Drepper gefordert) vorher bekannt war.
Patrick.Schluter
2017-02-06 17:17:42 UTC
Permalink
Raw Message
Post by Rainer Weikusat
Post by Patrick.Schluter
Post by Claus Reibenstein
benötigten strl*-Funktionen einfach selber bauen kann.
#include <string.h>
char *strlcpy(char *s1, const char *s2, size_t n) {
strncpy(s1, s2, n - 1);
s1[n - 1] = 0;
return s1;
}
strncpy() ist keine gute Basis für strlcpy(). strncpy() hat den großen
Nachteil den Puffer immer bis zum Anschlag mit Nullen
vollzuschreiben. Wenn dieser sehr gross ist kann dass schon ganz schön
teuer sein.
Hier ein simple Version
size_t strlcpy(char *dst, const char *src, size_t dstsize)
{
size_t len = strlen(src);
if(dstsize)
*((char*)mempcpy(dst, src, min(len, dstsize-1))) = 0;
return len;
}
Diese Version hat auch den Vorteil Ulrich Drepper's "Argument" gegen
strlcpy() in glibc ad absurdum zu führen.
Motto "If you can't dazzle them with brilliance, baffle them with
bullshit". Der referenzierte Text war
This is horribly inefficient BSD crap. Using these function only
leads to other errors. Correct string handling means that you always
know how long your strings are and therefore you can you memcpy
(instead of strcpy).
http://www.sourceware.org/ml/libc-alpha/2000-08/msg00053.html
Daraus, dass die oa Funktion die Stringlaenge durch Zeichenzaehlen
ermitteln muss, kann man entnehmen, dass diese Stringlaenge nicht (wie
von Drepper gefordert) vorher bekannt war.
Mir ging es mehr um diesen Eintrag
https://www.sourceware.org/ml/libc-alpha/2000-08/msg00061.html

in dem er mempcpy() benutzt. Das man strlcpy() in 3 Zeilen mit mempcpy()
implementieren kann fand ich ganz lustig.

In der Praxis ist es leider aber so dass man die Stringlänge eben nicht
vorher hat (und das sehr oft wegen fremder Libraries (auch glibc)),
deshalb ist gerade strlcpy() interessant. Da, wo er allerdings recht
hat, ist daß die *cat() Funktionen so gut wie nie sinnvoll sind. Das
degeneriert sehr schnell in versteckte O(n²)/O(n³) Komplexitäten.
Rainer Weikusat
2017-02-06 22:00:23 UTC
Permalink
Raw Message
"Patrick.Schluter" <***@free.fr> writes:

[strlcpy und U. Dreppers Meinung darueber]
Post by Patrick.Schluter
In der Praxis ist es leider aber so dass man die Stringlänge eben
nicht vorher hat (und das sehr oft wegen fremder Libraries (auch
glibc)), deshalb ist gerade strlcpy() interessant.
Hmm ... nicht besonders. Dreppers Ansicht ist durchaus sinnvoll,
lediglich ein bisschen schwer zu verstehen, weil er die Zwischenschritte
zwischen dem Diskussionsgegenstand und seiner Ansicht dazu als bekannt
vorraussetzt:

strlcpy kann man benutzen um eine String unbekannter
Laenge in einen Puffer bekannter Laenge zu kopieren ohne einen
Pufferueberlauf zu riskieren. Das ist aber unsinnig, denn den
Eingabestring einfach abzuschneiden, ist vielleicht weniger 'exploitbar'
als strcpy zu benutzen jedoch generell genauso falsch. Falls man den
String kopieren muss, muss man also vorher dessen Laenge ermitteln, um
einen geeignet grossen Puffer bereitstellen zu koennen. Hat man das
getan, kann man auch strcpy oder memcpy benutzen, da eine zweite
Laengenpruefung nicht notwendig ist.
Rainer Weikusat
2017-02-06 22:33:42 UTC
Permalink
Raw Message
Rainer Weikusat <***@talktalk.net> writes:

[...]
Post by Rainer Weikusat
strlcpy kann man benutzen um eine String unbekannter
Laenge in einen Puffer bekannter Laenge zu kopieren ohne einen
Pufferueberlauf zu riskieren. Das ist aber unsinnig, denn den
Eingabestring einfach abzuschneiden, ist vielleicht weniger 'exploitbar'
als strcpy zu benutzen jedoch generell genauso falsch. Falls man den
String kopieren muss, muss man also vorher dessen Laenge ermitteln, um
einen geeignet grossen Puffer bereitstellen zu koennen. Hat man das
getan, kann man auch strcpy oder memcpy benutzen, da eine zweite
Laengenpruefung nicht notwendig ist.
Die (ebenso begruendete) Gegenposition koennte ungefaehr wie folgt
aussehen:

strn* ist zu kompliziert und meistens ohnehin die falsche Wahl. Korrekt
implementierte dynamische Speicherverwaltung machen Die Idioten[tm]
sowieso nicht und selbst wenn sie das versuchen wuerden, wuerden sie es
nicht hinkriegen. Falls man sie also durch "slut shaming" dazu bekommen
kann, wenigstens einen Buchstaben mehr zu tippen, ist ihr daemliches Programm
hinterher zwar immer noch kaputt, aber wenigstens gibt es deswegen keine
System-Einbrueche.
Patrick.Schluter
2017-02-07 06:48:03 UTC
Permalink
Raw Message
Post by Rainer Weikusat
[...]
Post by Rainer Weikusat
strlcpy kann man benutzen um eine String unbekannter
Laenge in einen Puffer bekannter Laenge zu kopieren ohne einen
Pufferueberlauf zu riskieren. Das ist aber unsinnig, denn den
Eingabestring einfach abzuschneiden, ist vielleicht weniger 'exploitbar'
als strcpy zu benutzen jedoch generell genauso falsch. Falls man den
String kopieren muss, muss man also vorher dessen Laenge ermitteln, um
einen geeignet grossen Puffer bereitstellen zu koennen. Hat man das
getan, kann man auch strcpy oder memcpy benutzen, da eine zweite
Laengenpruefung nicht notwendig ist.
Die (ebenso begruendete) Gegenposition koennte ungefaehr wie folgt
strn* ist zu kompliziert und meistens ohnehin die falsche Wahl. Korrekt
implementierte dynamische Speicherverwaltung machen Die Idioten[tm]
sowieso nicht und selbst wenn sie das versuchen wuerden, wuerden sie es
nicht hinkriegen. Falls man sie also durch "slut shaming" dazu bekommen
kann, wenigstens einen Buchstaben mehr zu tippen, ist ihr daemliches Programm
hinterher zwar immer noch kaputt, aber wenigstens gibt es deswegen keine
System-Einbrueche.
imo das Grundproblem von strncpy (strncat weiss ich nicht, wie gesagt
*cat Funktionen verwende ich nie) ist das Löschen des Puffers, nicht
wirklich das NUL byte (wie oft hab ich so einen Mist in Code gesehen:

#define SIZE 32768
char buffer[SIZE] = {0};
strncpy(buffer, "Hallo", SIZE-1);

Aua, zwei memset(buffer, 0, SIZE) für nichts.
Rainer Weikusat
2017-02-07 15:52:35 UTC
Permalink
Raw Message
Post by Patrick.Schluter
Post by Rainer Weikusat
[...]
Post by Rainer Weikusat
strlcpy kann man benutzen um eine String unbekannter
Laenge in einen Puffer bekannter Laenge zu kopieren ohne einen
Pufferueberlauf zu riskieren. Das ist aber unsinnig, denn den
Eingabestring einfach abzuschneiden, ist vielleicht weniger 'exploitbar'
als strcpy zu benutzen jedoch generell genauso falsch. Falls man den
String kopieren muss, muss man also vorher dessen Laenge ermitteln, um
einen geeignet grossen Puffer bereitstellen zu koennen. Hat man das
getan, kann man auch strcpy oder memcpy benutzen, da eine zweite
Laengenpruefung nicht notwendig ist.
Die (ebenso begruendete) Gegenposition koennte ungefaehr wie folgt
strn* ist zu kompliziert und meistens ohnehin die falsche Wahl. Korrekt
implementierte dynamische Speicherverwaltung machen Die Idioten[tm]
sowieso nicht und selbst wenn sie das versuchen wuerden, wuerden sie es
nicht hinkriegen. Falls man sie also durch "slut shaming" dazu bekommen
kann, wenigstens einen Buchstaben mehr zu tippen, ist ihr daemliches Programm
hinterher zwar immer noch kaputt, aber wenigstens gibt es deswegen keine
System-Einbrueche.
imo das Grundproblem von strncpy (strncat weiss ich nicht, wie gesagt
*cat Funktionen verwende ich nie) ist das Löschen des Puffers, nicht
#define SIZE 32768
char buffer[SIZE] = {0};
strncpy(buffer, "Hallo", SIZE-1);
Aua, zwei memset(buffer, 0, SIZE) für nichts.
"Lennart Poettering was here!" (

Abteilung "was man sich haette denken koennen" (waere die einfach
verfuegbare Dokumentation weniger sinnlos/ wirr):

Strncpy copies exactly n characters, truncating or
null-padding s2;

http://man.cat-v.org/unix_7th/3/string
Patrick.Schluter
2017-02-07 06:41:20 UTC
Permalink
Raw Message
Post by Rainer Weikusat
[strlcpy und U. Dreppers Meinung darueber]
Post by Patrick.Schluter
In der Praxis ist es leider aber so dass man die Stringlänge eben
nicht vorher hat (und das sehr oft wegen fremder Libraries (auch
glibc)), deshalb ist gerade strlcpy() interessant.
Hmm ... nicht besonders. Dreppers Ansicht ist durchaus sinnvoll,
lediglich ein bisschen schwer zu verstehen, weil er die Zwischenschritte
zwischen dem Diskussionsgegenstand und seiner Ansicht dazu als bekannt
strlcpy kann man benutzen um eine String unbekannter
Laenge in einen Puffer bekannter Laenge zu kopieren ohne einen
Pufferueberlauf zu riskieren. Das ist aber unsinnig, denn den
Eingabestring einfach abzuschneiden, ist vielleicht weniger 'exploitbar'
als strcpy zu benutzen jedoch generell genauso falsch. Falls man den
String kopieren muss, muss man also vorher dessen Laenge ermitteln, um
einen geeignet grossen Puffer bereitstellen zu koennen. Hat man das
getan, kann man auch strcpy oder memcpy benutzen, da eine zweite
Laengenpruefung nicht notwendig ist.
Oder man verwendet einen schon standardgrossen Puffer der in 99.99...%
der Fälle in Grösse aussreicht
und checkt den Returnwert von strlcpy(). Wenn der String gepasst hat hat
man die Länge und die Kopie des String schon hinter sich und kann
weitermachen. Wenn nicht, kann man dann machen was man will, entweder
realloc() und den Rest des Strings kopieren oder Maulen was das Zeug
hällt. Wer, allerdings den returnwert nicht anschaut verdient seine
Stringabschneidung (die aber durchaus auch das richtige Verhalten sein
kann).
Kann man das ohne strlpcy()? Na sicher kann man das. Man kann auch ohne
for() und while() eine Schleife mit if und goto bauen. Aber muss das sein?
Wer strlcpy() nicht mag muss es nicht verwenden aber diese Funktion
einer nicht zu vernachlässigen Anzahl von Programmierern vorzuenthalten
nur weil man an NIH Syndrom leidet ist 'ne andere Geschichte (es ist ja
nicht so dass es ein spezifischer Linux hass auf diese Funktion ist, da
sie im Kernel durchaus verwendet wird).
Rainer Weikusat
2017-02-07 16:46:17 UTC
Permalink
Raw Message
Post by Patrick.Schluter
Post by Rainer Weikusat
[strlcpy und U. Dreppers Meinung darueber]
Post by Patrick.Schluter
In der Praxis ist es leider aber so dass man die Stringlänge eben
nicht vorher hat (und das sehr oft wegen fremder Libraries (auch
glibc)), deshalb ist gerade strlcpy() interessant.
Hmm ... nicht besonders. Dreppers Ansicht ist durchaus sinnvoll,
lediglich ein bisschen schwer zu verstehen, weil er die Zwischenschritte
zwischen dem Diskussionsgegenstand und seiner Ansicht dazu als bekannt
strlcpy kann man benutzen um eine String unbekannter
Laenge in einen Puffer bekannter Laenge zu kopieren ohne einen
Pufferueberlauf zu riskieren. Das ist aber unsinnig, denn den
Eingabestring einfach abzuschneiden, ist vielleicht weniger 'exploitbar'
als strcpy zu benutzen jedoch generell genauso falsch. Falls man den
String kopieren muss, muss man also vorher dessen Laenge ermitteln, um
einen geeignet grossen Puffer bereitstellen zu koennen. Hat man das
getan, kann man auch strcpy oder memcpy benutzen, da eine zweite
Laengenpruefung nicht notwendig ist.
Oder man verwendet einen schon standardgrossen Puffer der in 99.99...%
der Fälle in Grösse aussreicht
und checkt den Returnwert von strlcpy(). Wenn der String gepasst hat
hat man die Länge und die Kopie des String schon hinter sich und kann
weitermachen. Wenn nicht, kann man dann machen was man will, entweder
realloc() und den Rest des Strings kopieren oder Maulen was das Zeug
hällt.
Man kann einen Puffer benutzen, von dem man annimmt, dass er meistens
viel zu gross sein wird, und sich somit um den Preis einer
Speicherverschwendung, die man als erheblich ansehen kann, sowie von
vermeidbarem 'Ausnahmesituationbehandlungscode' (den irgendjemand
irgendwann ganz bestimmt schreibt :-) hoffentlich einen strlen-Aufruf
und einen malloc/ alloca Aufruf sparen.

- an dieser Stelle wird dem C++-Programmierer, als zB Drepper, ganz
furchtbar uebel und er faengt an, Brocken, die wie std, :: und string
aussehen, rueckwaerts zu essen -

J***@fokus.fraunhofer.de
2016-11-07 10:24:02 UTC
Permalink
Raw Message
Post by Thomas Koenig
[x-post, F'up nach de.comp.lang.c]
Im Linux Umfeld weigert man sich z.B. immer noch die strl*()
Funktionen in libc zu integrieren obwohl es keine bessere Methode gibt mit
begrenztem String-Speichern umzugehen.
Wer oder was sind die strl* - Funktionen?
Du könntest mit "man strlcpy" anfangen....

Diese Funktionen tauchten im Sommer 1988 bei OpenBSD auf, wurden dann Anfang
1999 in Solaris übernommen und gegen Ende 1999 auch in FreeBSD.

Sie sind eigentlich in allen ernstzunehmenden UNIX Varianten ferfügbar.

Sie vermeiden Das Performance Problem mit strncpy() und garantieren
darüberhinaus auch daß der Zielstring immer mit einem Nullbyte abgeschlossen
ist.
--
EMail:***@schily.net (home) Jörg Schilling D-13353 Berlin
***@fokus.fraunhofer.de (work) Blog: http://schily.blogspot.com/
URL: http://cdrecord.org/private/ http://sourceforge.net/projects/schilytools/files/
Michael Bäuerle
2016-11-07 11:10:19 UTC
Permalink
Raw Message
Post by J***@fokus.fraunhofer.de
Post by Thomas Koenig
Im Linux Umfeld weigert man sich z.B. immer noch die strl*()
Funktionen in libc zu integrieren obwohl es keine bessere Methode gibt mit
begrenztem String-Speichern umzugehen.
Wer oder was sind die strl* - Funktionen?
Du könntest mit "man strlcpy" anfangen....
Thomas hat aber mit GNU/Linux gepostet, und da ergibt das bei mir:
|
| $ man strlcpy
| No manual entry for strlcpy
Post by J***@fokus.fraunhofer.de
Diese Funktionen tauchten im Sommer 1988 bei OpenBSD auf, wurden dann Anfang
1999 in Solaris übernommen und gegen Ende 1999 auch in FreeBSD.
NetBSD hat sie auch (Laut man page seit Version 1.4.3).
Thomas Koenig
2016-11-07 13:11:28 UTC
Permalink
Raw Message
Post by J***@fokus.fraunhofer.de
Du könntest mit "man strlcpy" anfangen....
Diese Funktionen tauchten im Sommer 1988 bei OpenBSD auf, wurden dann Anfang
1999 in Solaris übernommen und gegen Ende 1999 auch in FreeBSD.
Sie sind eigentlich in allen ernstzunehmenden UNIX Varianten ferfügbar.
Stellt sich jetzt die Frage: Ist Linux kein UNIX oder ist Linux nicht
ernstzunehmen?
Stefan Kanthak
2016-11-07 19:27:12 UTC
Permalink
Raw Message
Post by Thomas Koenig
[x-post, F'up nach de.comp.lang.c]
Im Linux Umfeld weigert man sich z.B. immer noch die strl*()
Funktionen in libc zu integrieren obwohl es keine bessere Methode gibt mit
begrenztem String-Speichern umzugehen.
Wer oder was sind die strl* - Funktionen?
Mach Dich bei OpenBSD schlau.

Stefan
[
--
Die unaufgeforderte Zusendung werbender E-Mails verstoesst gegen §823
Abs. 1 sowie §1004 Abs. 1 BGB und begruendet Anspruch auf Unterlassung.
Beschluss des OLG Bamberg vom 12.05.2005 (AZ: 1 U 143/04)
Loading...