mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Vorteile memcmp memcpy


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: Kai (Gast)
Datum:

Bewertung
-3 lesenswert
nicht lesenswert
Guten Morgen,
wie viel vorteilhafter sind die Funktionen memcpy und memcmp in c? Wenn 
ich z. B. einen array mit 128 Einträgen habe. Lohnt es sich diese 
Funktionen zu benutzen? Quasi könnte man das auch alles mit einer 
for-loop machen. Wenn man diese Funktionen nicht verwenden würde, 
bräuchte man auch die libs nicht zu inkludieren (es sei denn man 
verwendet andere Funktionen aus dieser lib),was Platz sparen würde.

Kai

Autor: Michael B. (laberkopp)
Datum:

Bewertung
2 lesenswert
nicht lesenswert
Kai schrieb:
> Wenn man diese Funktionen nicht verwenden würde,
> bräuchte man auch die libs nicht zu inkludieren

Guck dir mal an, wie die bei Microsoft und Intel aufgebaut sind

https://github.com/dotnet/coreclr/blob/master/src/vm/arm/memcpy.asm

https://github.com/intel/intel-ipsec-mb/blob/master/include/memcpy.asm

und dann überlege, ob dein Compiler aus

https://github.com/gcc-mirror/gcc/blob/master/libgcc/memcpy.c

dasselbe macht.
Und dann überlege, warum Intel und Microsoft so einen Aufwand treiben.

Autor: Dr. Sommer (Gast)
Datum:

Bewertung
2 lesenswert
nicht lesenswert
Kai schrieb:
> Wenn man diese Funktionen nicht verwenden würde, bräuchte man auch die
> libs nicht zu inkludieren (es sei denn man verwendet andere Funktionen
> aus dieser lib),was Platz sparen würde.

Du glaubst also, dass deine eigene Funktion kleiner wäre? Da sie aber 
nicht so stark optimiert ist, langsamer? Dann musst du wissen, was dir 
wichtiger ist. Kompilieren beide Varianten und vergleiche das Ergebnis.

Autor: Kaj (Gast)
Datum:

Bewertung
5 lesenswert
nicht lesenswert
Kai schrieb:
> Quasi könnte man das auch alles mit einer
> for-loop machen.
Warum sollte man einen 1-Zeiler:
memcpy(...);
unnoetig aufblasen?
for(...) {
    a[i] = ...;
}


Ein Vorteil von memcpy & Co.: Jeder sieht sofort am Namen was da 
passiert. Bei einer Schleife muss man erstmal in die Schleife reingucken 
und analysieren was da passiert.

Autor: M. K. (sylaina)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kai schrieb:
> Lohnt es sich diese
> Funktionen zu benutzen?
Na klar, warum sollte es sich nicht lohnen. Die Funktionen stehen nicht 
umsonst in den Standardlibs eines jeden C-Compilers drin. ;)
Kai schrieb:
> Quasi könnte man das auch alles mit einer
> for-loop machen.

Dann schau doch mal in memcpy und memcmp rein ;)

Kai schrieb:
> Wenn man diese Funktionen nicht verwenden würde,
> bräuchte man auch die libs nicht zu inkludieren (es sei denn man
> verwendet andere Funktionen aus dieser lib),was Platz sparen würde.

Das kommt auf deine Lösung an, das kann man nicht pauschal sagen, dass 
eigene Funktionen Platz sparen ;)

Autor: Arduino Fanboy D. (ufuf)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kai schrieb:
> bräuchte man auch die libs nicht zu inkludieren (es sei denn man
> verwendet andere Funktionen aus dieser lib),was Platz sparen würde.
Lustige Idee!

Zumindest über mein System kann ich sagen, dass keine unbenutzten Lib 
Funktionen eingebunden werden.

Ist das bei dir anderes?
Warum?

Autor: Axel S. (a-za-z0-9)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Kai schrieb:

> wie viel vorteilhafter sind die Funktionen memcpy und memcmp in c?

Die Frage ist unvollständig. Wieviel vorteilhafter im Vergleich womit? 
Und welche Eigenschaften des Programms betrachtest du, um einen Vorteil 
zu erkennen? Ausführungsgeschwindigkeit? Codegröße? Korrektheit?

> Wenn
> ich z. B. einen array mit 128 Einträgen habe. Lohnt es sich diese
> Funktionen zu benutzen?

Probiere es halt aus.

> Wenn man diese Funktionen nicht verwenden würde,
> bräuchte man auch die libs nicht zu inkludieren

Libs werden nicht includiert. Hederfiles werden includiert. Libs werden 
(dazu) gelinkt. Und es gibt kein Geld zurück, wenn man Libraryfunktionen 
nicht verwendet. Genauso wie es auch kein Geld zurück gibt für 
ungenutzten Flashspeicher.

Funktionen aus der Standardbibliothek sind meist hochoptimiert, nicht 
selten sind wesentliche Teile in Assembler formuliert. In den meisten 
Fällen sind diese Funktionen daher schneller und oft auch kleiner als 
eine händisch hingeschriebene Lösch- oder Kopierschleife.

Autor: S. R. (svenska)
Datum:

Bewertung
2 lesenswert
nicht lesenswert
Die vier Funktionen memcmp, memcpy, memmove und memset sind im 
Zusammenhang mit gcc speziell. Der Compiler darf jederzeit Aufrufe zu 
diesen Funktionen generieren - auch ohne libc - und tut das, wenn 
möglich auch.

Deine for-Schleife könnte also vom Compiler durch ein memcpy/memmove 
ersetzt werden.

Autor: Jörg W. (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
5 lesenswert
nicht lesenswert
S. R. schrieb:
> Die vier Funktionen … mit gcc speziell.

Nein.  Nicht nur diese, und nicht nur mit GCC.

Alle Funktionen der Standardbibliothek sind „speziell“ und dürfen in 
einem hosted environment vom Compiler so implementiert werden, dass er 
implizites Wissen darüber besitzt, was sie tun.

Das ist eine gute Sache, denn ich kann beispielsweise schreiben:
#define MSG "foobar"

// …

   memcpy(target, MSG, strlen(MSG));

… und der Compiler kann implizit auf eine ihm genehme Weise die 6 
Zeichen des Strings "foobar" an die Zieladresse übertragen. Insbesondere 
ist er nicht verpflichtet, für das strlen() irgendwie erst einen 
Funktionsaufruf zu generieren, denn es ist völlig klar, dass dieser 
immer eine 6 ergeben würde.

Auch ein memcpy() eines einzelnen Zeichens wird wohl so ziemlich jeder 
Compiler auf diese Weise inline auflösen können, ohne erst irgendwelche 
Funktionen zu bemühen. Schließlich und endlich könnte das System aus 
Compiler und Bibliothek ("the implementation") auch Sonderfälle haben, 
bei denen dem Compiler bekannt ist, dass unter bestimmten Umständen 
Dinge optimierbar sind, die nicht direkt aus dem Quelltext ersichtlich 
sind (bspw. Kopien in kompletten 32- oder 64-Bit-Einheiten durchführbar, 
wenn die Adressen passend ausgerichtet sind).

Kai schrieb:
> Quasi könnte man das auch alles mit einer for-loop machen.

Das wäre dann die worst-case-Implementierung. Eine solche primitive 
Implementierung wird wohl jede Standardbibliothek allemal vorhalten 
können, in der Regel aber (wie bereits geschrieben worden ist) wird sie 
sehr wahrscheinlich eine bessere Implementierung anbieten können.

Aber dein Grund-Missverständnis war ja offensichtlich ohnehin, dass das 
"Inkludieren" (also Linken) einer Bibliothek in irgendeiner Form da 
gleich alles reinziehen würde, was sonst noch in der Bibliothek 
vorhanden ist. Dem ist natürlich nicht so.

: Bearbeitet durch Moderator
Autor: keinerniemand (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kurz mein Senf dazu:

ich arbeite meist mit zeitkritischen Messsystemen, wo also 10 us schon 
zu einer Verzögerung führen können. Da hab ich dann einfach mal memcpy 
und eine for-loop zeitlich verglichen.

Also mit einem toggelden uC-Pin am Oszilloskop, bei mir kam meine ich 
heraus, dass memcpy bei großen arrays zeit spart und eine for-loop bei 
deinen 128 Bytes noch schneller sein sollte, eventuell wegen overheads 
oder so, ich hab da jetzt nicht genauer reingeschaut und alle 
eventualitäten abgeprüft, aber in meinem kruden Fall kam eben heraus das 
eine for-loop zeit spart, jetzt dürfen sich die Experten melden wieso 
das stimmt oder eventuell auch nicht :)

Viele Grüße.

Autor: Jörg W. (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
keinerniemand schrieb:
> eine for-loop bei deinen 128 Bytes noch schneller sein sollte, eventuell
> wegen overheads oder so

Das hängt natürlich ganz entscheidend davon ab:

* welchen Prozessor du überhaupt benutzt
* wie "intelligent" der Compiler ist

Wie ich schon schrieb, ist es durchaus möglich, dass ein Compiler auch 
solche Effekte "kennt" und berücksichtigen kann, d.h. einen 
Funktionsaufruf nur dann generiert, wenn ihm klar ist, dass der einen 
Vorteil bringt.

Pauschal kann man daher gar nichts sagen. Sowas im Einzelfall auf paar 
Mikrosekungen mit der Hand zu "optimieren" riskiert stets, dass es mit 
der nächsten Compilerversion wieder zerbricht, weil dort alles ganz 
anders umgesetzt wird.

Autor: zitter_ned_aso (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kai schrieb:
> Wenn
> ich z. B. einen array mit 128 Einträgen habe. Lohnt es sich diese
> Funktionen zu benutzen? Quasi könnte man das auch alles mit einer
> for-loop machen.

Na eben.

Du prüfst nicht den gesamten Specherblock für 128 Einträge gleichzeitig, 
sondern jeden Eintrag einzeln. Also wieder irgendeine Schleife. Ob da 
memcmp wirlich was bringt....

Autor: A. S. (achs)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Jörg W. schrieb:
> S. R. schrieb:
>> Die vier Funktionen … mit gcc speziell.
>
> Nein.  Nicht nur diese, und nicht nur mit GCC.

Die Aussage von S.R. war ein andere, nämlich: Der GCC darf, wenn er den 
Code des TO sieht, memcpy aufrufen obwohl der TO es nirgends nutzt.

Axel S. schrieb:
> Libs werden
> (dazu) gelinkt. Und es gibt kein Geld zurück, wenn man Libraryfunktionen
> nicht verwendet.

Für den TO musst Du aber noch dazu sagen, dass aus eine LIB nur genau 
die Einheiten ("~C-Files~") dazu gelinkt werden, die gebraucht werden.

Darum steht z.B. die Funtkion abs() (so sie als Funktion implementiert 
ist) meist in einer eigenen Datei, damit nur genau diese 5 Bytes (oder 
so) Code dazugelinkt werden.

Also auch wenn aller Code (printf und Co) einer Lib zusammen mehrere MB 
belegen würde, der Compiler macht cherry-Picking. Bei Komplexen 
Funktionen (z.b. printf) geht das allerdings nicht immer, so dass es 
hier manchmal extra Compiler (Linker)-Schalter gibt, mit denen man z.B. 
Floating-Point Unterstützung AN oder AUSschalten kann.

Autor: GEKU (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kai schrieb:
> Wenn man diese Funktionen nicht verwenden würde,
> bräuchte man auch die libs nicht zu inkludieren (es sei denn man
> verwendet andere Funktionen aus dieser lib),was Platz sparen würde.

Das verwenden der Lib-Funktionen macht Sinn. Man braucht sich mit einem 
Debugger die Funktionen ansehen. Einfacherer Code geht nicht mehr.

Der Linker binden nur jenen Code ein, der verwendet wird! Es entsteht 
durch die Verwendung von Librarys kein Overhead.

Autor: GEKU (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Axel S. schrieb:
> Standardbibliothek sind meist hochoptimiert

und vor Allem gut getestet!

Autor: Gebhard R. (geb)
Datum:

Bewertung
-6 lesenswert
nicht lesenswert
memcpy kopiert IMHO Byteweise. Mit einer for-Schleife könnte man 4Byte 
Integer kopieren, was zumindest bei einer 32 Bit Architektur schneller 
sein sollte.

Grüsse

Autor: Dr. Sommer (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Gebhard R. schrieb:
> memcpy kopiert IMHO Byteweise.

Hat diese persönliche Meinung auch eine Quelle? Nein, es muss nur dazu 
in der Lage sein, einzelne Bytes zu kopieren. Es kann sehr wohl 
effizienter implementiert sein. Es könnte z.B. automatisch erkennen wenn 
die Adressen 4-Byte-Aligned sind und dann entsprechende Instruktionen 
nutzen, z.B. LDM und STM auf ARM.

Autor: Gebhard R. (geb)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Dr. Sommer schrieb:
> Es könnte z.B. automatisch erkennen wenn
> die Adressen 4-Byte-Aligned sind

könnte ist jetzt aber auch Konjunktiv! Weiß wer was genaueres?

Grüsse

Autor: Dr. Sommer (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Gebhard R. schrieb:
> Weiß wer was genaueres?

Der Quelltext der C Bibliothek und des Compilers der jeweiligen 
Plattform. Bei der newlib  z.B. ist das so.

Autor: Jörg W. (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. S. schrieb:

>> Nein.  Nicht nur diese, und nicht nur mit GCC.
>
> Die Aussage von S.R. war ein andere, nämlich: Der GCC darf, wenn er den
> Code des TO sieht, memcpy aufrufen obwohl der TO es nirgends nutzt.

Wobei ich das noch nirgends in freier Wildbahn erlebt habe.

> Bei Komplexen
> Funktionen (z.b. printf) geht das allerdings nicht immer, so dass es
> hier manchmal extra Compiler (Linker)-Schalter gibt, mit denen man z.B.
> Floating-Point Unterstützung AN oder AUSschalten kann.

Das liegt schlicht und ergreifend nicht daran, dass printf per se 
"komplex" ist, sondern dass es erst zur Laufzeit anhand seiner 
Format-Strings entscheidet, welche Umwandlungen wirklich erfolgen 
müssen. Daher müssen sie als Bibliothekscode erst einmal alle verfügbar 
sein. Für (zur Compileizeit) konstante Format-Strings könnte man sich 
noch vorstellen, dass das System aus Compiler, Linker und Bibliothek da 
irgendwelche Analysen und Entscheidungen durchführt, aber Format-Strings 
lassen sich natürlich auch prinzipiell erst zur Laufzeit 
zusammenbasteln.

Autor: Dr. Sommer (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Dr. Sommer schrieb:
> Der Quelltext der C Bibliothek und des Compilers der jeweiligen
> Plattform. Bei der newlib  z.B. ist das so.

Hier zu bewundern:

https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;a=blob;f=newlib/libc/string/memcpy.c

Es wird sogar nach Konfigurations-Einstellungen unterschieden.

Die newlib wird z.B. vom GCC-ARM-Embedded genutzt, welcher bei vielen 
Cortex-M-IDEs mitgeliefert wird.

Jörg W. schrieb:
> Daher müssen sie als Bibliothekscode erst einmal alle verfügbar
> sein.

Genau - da steht im Code z.B. so etwas à la "if (format == 'f') 
format_float(arg);". Dass dieser Fall nie eintritt, kann der Compiler 
nicht sehen, insbesondere weil das ja bereits vorkompiliert in der 
Bibliothek vorliegt.

Autor: S. R. (svenska)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Jörg W. schrieb:
>>> Nein.  Nicht nur diese, und nicht nur mit GCC.
>> Die Aussage von S.R. war ein andere, nämlich: Der GCC darf, wenn er den
>> Code des TO sieht, memcpy aufrufen obwohl der TO es nirgends nutzt.
> Wobei ich das noch nirgends in freier Wildbahn erlebt habe.

Steht in der Manpage:
https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Link-Options.html
dort unter z.B. -nostdlib oder -nodefaultlibs:
"The compiler may generate calls to memcmp, memset, memcpy and memmove."

Wenn man größere Strukturen kopiert und auf Codegröße optimiert, dann 
sieht man das auch in freier Wildbahn.

Wird dann interessant, wenn man memcpy implementieren möchte:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56888

Autor: Jörg W. (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
S. R. schrieb:
> Wenn man größere Strukturen kopiert

Ja, gut, dafür kann ich mir es in der Tat vorstellen.

Autor: A. K. (prx)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Gebhard R. schrieb:
> memcpy kopiert IMHO Byteweise.

Nur wenn der Programmierer zu faul war, es besser zu machen.

Autor: A. K. (prx)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Gebhard R. schrieb:
>> Es könnte z.B. automatisch erkennen wenn
>> die Adressen 4-Byte-Aligned sind
>
> könnte ist jetzt aber auch Konjunktiv! Weiß wer was genaueres?

Entscheidend ist nur, was hinten rauskommt. Es gibt klar definierte 
Randbedingungen, innerhalb derer die Implementierung von memcpy tun 
darf, was sie will. Viel genauer wirds nicht.

Berücksichtigung von Alignment ist ein uralter Hut.

Der Microcode von Intel/AMD x86 optimiert Befehle wie REP MOVS ebenfalls 
abhängig von Alignment, Anzahl Interationen und wassweissich. Da dürften 
dann auch die Caches Berücksichtigung finden.

: Bearbeitet durch User
Autor: x^y (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Speziell zum GCC kann ich noch sagen:

Mit dem GCC (neue Versionen) habe ich festgestellt, dass Aufrufe von 
memcpy() auch vom Compiler ausoptimiert werden können (er hat 
tatsächlich nur noch LDR/STR Instruktionen inline generiert). Ich habe 
es nicht im Detail nachverfolgt, sondern nur das passende Compiler Flag 
gesucht womit man dies abschalten konnte. Hier nur ein Link als 
Ansatzpunkt dafür, dass ich keinen Mist erzähle :-)

https://stackoverflow.com/questions/11747891/when-builtin-memcpy-is-replaced-with-libcs-memcpy

In vorgenannten Fall hatte der Compiler dies für ein relativ kleines und 
zur Compilezeit bekanntes N getan. Aufgefallen ist das aber dadurch, 
dass der Compiler dabei das Alignment nicht mehr korrekt berücksichtigte 
was eine Exception generierte.

GCC Library Funktionen sind heute mehr auf Geschwindigkeit wie Größe 
ausgelegt. Entsprechend kann es dann sinnvoller sein die Library zu 
nutzen. Natürlich muss die Problemgröße hinreichend groß sein, damit 
diese Funktionen ihren Vorteil ausspielen können. Die Geschwindigkeit 
wird i.d.R. über Konstruktionen wie Duff's device

https://de.wikipedia.org/wiki/Duff%E2%80%99s_Device

und plattformspezifische Optimierungen (z.B. Laden/Speichern via LDM/STM 
unter Nutzung mehrerer Register). Typisch auch das Erweitern der 
Datengröße bis Erreichung des maximalen Alignments (LDRB/STRB => 
LDRH/STRH => LDR/STR).

Falls hingegen die Größe der Funktion ein Argument ist (eher 
Embedded-Bereich), kann es sinnvoll sein diese Implementierungen durch 
eigene zu ersetzen. Wir tun dies, wobei diese Implementierungen 
zusätzlich NULL Pointer-Safe sind und mit überlappenden 
Speicherbereichen generell korrekt funktionieren. Dies ist btw. der 
subtile Unterschied zwischen Standard memcpy() und memmove().

Autor: Jörg W. (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
2 lesenswert
nicht lesenswert
x^y schrieb:
> GCC Library Funktionen sind heute mehr auf Geschwindigkeit wie Größe
> ausgelegt.

Kannst du so pauschal nicht sagen, denn es gibt nicht allgemein „GCC 
Library Funktionen“. Die Standardbibliothek wird nicht vom GCC-Team 
selbst gepflegt, sondern es gibt sehr verschiedene Implementierungen 
dafür: glibc, BSD libc, newlib (teils BSD, teils aus anderen Quellen 
zusammengekramt), avr-libc, …

> Wir tun dies, wobei diese Implementierungen
> zusätzlich NULL Pointer-Safe sind und mit überlappenden
> Speicherbereichen generell korrekt funktionieren. Dies ist btw. der
> subtile Unterschied zwischen Standard memcpy() und memmove().

Eben. Daher halte ich es für unsinnig, auch memcpy() wie memmove() zu 
implementieren, denn das verhindert Optimierungen. Das ist ja auch der 
einzige Grund, warum es überhaupt für praktisch die gleiche Aufgabe im 
Standard zwei verschiedene Funktionen gibt.

Auch NULL-Pointer-safe finde ich Quatsch, es hilft höchstens, Bugs zu 
kaschieren statt sie zu entdecken.

Autor: x^y (Gast)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Jörg W. schrieb:
> Eben. Daher halte ich es für unsinnig, auch memcpy() wie memmove() zu
> implementieren, denn das verhindert Optimierungen. Das ist ja auch der
> einzige Grund, warum es überhaupt für praktisch die gleiche Aufgabe im
> Standard zwei verschiedene Funktionen gibt.
>
> Auch NULL-Pointer-safe finde ich Quatsch, es hilft höchstens, Bugs zu
> kaschieren statt sie zu entdecken.

Kann man so sehen, unsere Sicht bzw. Philosophie ist da anders. M.M. 
gibt es da kein "richtig" und "falsch" weswegen ich unsere Gründe gerne 
darlege:

Unser Ansatz ist undefiniertes Verhalten nach bester Möglichkeit auf 
allen Ebenen zu verhindern, indem definiertes Verhalten implementiert 
wird. Ebenen können sein: Einzelne Anweisungen (z.B. ++x + x++), 
Funktionen, Module, Libraries, usw. Für uns hat sich gezeigt, dass dies 
zu sehr zuverlässiger Software führt und nicht etwa das Auffinden von 
Fehlern erschwert.

Wenn ich sagen würde, dass es gut ist Funktionen zu nutzen, so dass 
undefiniertes Verhalten entstehen kann, muss ich konsequenterweise doch 
auch sagen, dass es gut ist Anweisungen auszuführen bei denen 
undefiniertes Verhalten entstehen kann - z.B. Signed overflow nicht 
durch Checks/Limitierung zu verhindern. Das kann aber nur in Situationen 
richtig sein, in denen ich mir sicher bin, dass diese Fälle -nicht 
eintreten können- wodurch ich dann einen Optimierungsvorteil habe bzw. 
gewinne. Wenn diese Fälle aber eintreten können, darf ich so nicht 
denken. Dann erlaube ich die Entstehung von undefiniertem Verhalten was 
keinesfalls zu einer "Erkennung" des Fehlers führen muss.

Zieht man unseren Ansatz konsequent durch, zeigt sich oft, dass ein 
Fehler entweder gar keinen Effekt mehr hat oder auf höherer Ebene 
automatisch behandelt wird. Es ist sehr schwierig das zu erklären oder 
glaubhaft zu machen, man muss es in gewisser Weise einfach erlebt haben 
:-)

Ich versuche mich trotzdem an einem Beispiel:
if (0 == memcmp(user_getname(), "Hans"))
{
   // greet Hans here
   send("Hi Hans, how are you?");
}

Fiktives Beispiel, aber hätte sich kein Benutzer angemeldet, würde die 
Funktion user_getname() NULL zurückliefern, was der Programmierer hier 
übersehen hätte. Was wäre die Konsequenz?

a) Klassisches memcmp()

Wenn an Adresse 0 kein Speicher vorliegt, undefiniertes Verhalten. 
Wahrscheinlich Exception/Neustart/Absturz. Wenn an Adresse 0 Speicher 
ist, undefiniertes Ergebnis, vermutlich FALSE aber mit einer geringen 
Restwahrscheinlichkeit TRUE. Auch hier bliebe erstmal eine prompte 
"Erkennung" des Fehler aus, da keine Exception, jedoch ist -das Ergebnis 
undefiniert- und das ist der Unterschied zur Variante b.

b) memcmp() NULL pointer safe

Definition der Funktion könnte sein: Vergleiche mit NULL Pointer liefern 
immer FALSE, außer NULL selbst. Benutzer ist also immer nicht "Hans". 
Dies muss korrekt sein, definiert man NULL als Zeiger "auf Nichts", dann 
kann "etwas" ja nie identisch sein zu "nichts". Das Verhalten von 
memcmp() ist also nicht unlogisch oder falsch, aber eben -immer 
definiert-.

Autor: Michael B. (laberkopp)
Datum:

Bewertung
-2 lesenswert
nicht lesenswert
x^y schrieb:
> Fiktives Beispiel

Kompiliert nicht, taugt eh nicht.

memcmp fehlt die Länge, und strcmp wäre passender, und schon lange gibt 
es lstrcmp

Autor: Philipp Klaus K. (Firma: Albert-Ludwigs-Universität) (pkk)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
A. K. schrieb:
> Gebhard R. schrieb:
>>> Es könnte z.B. automatisch erkennen wenn
>>> die Adressen 4-Byte-Aligned sind
>>
>> könnte ist jetzt aber auch Konjunktiv! Weiß wer was genaueres?
>
> Entscheidend ist nur, was hinten rauskommt. Es gibt klar definierte
> Randbedingungen, innerhalb derer die Implementierung von memcpy tun
> darf, was sie will. Viel genauer wirds nicht.
>
> Berücksichtigung von Alignment ist ein uralter Hut.
>
> Der Microcode von Intel/AMD x86 optimiert Befehle wie REP MOVS ebenfalls
> abhängig von Alignment, Anzahl Interationen und wassweissich. Da dürften
> dann auch die Caches Berücksichtigung finden.

memcpy() ist wichtig. Da wird sich wohl jede C-Implementierung bemühen, 
das möglichst effizient zu machen. Und wenn es auf Alignment ankommt, 
wird die Implementierung das berücksichtigen.
Das gilt auch für andere oft verwendete Bibliotheksfuntionen wie 
memcmp(), memset(), strchr(), strcpy(), strncpy(), etc.

Philipp

Autor: Jemand (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
x^y schrieb:
> Definition der Funktion könnte sein: Vergleiche mit NULL Pointer liefern
> immer FALSE, außer NULL selbst. Benutzer ist also immer nicht "Hans".
> Dies muss korrekt sein, definiert man NULL als Zeiger "auf Nichts", dann
> kann "etwas" ja nie identisch sein zu "nichts". Das Verhalten von
> memcmp() ist also nicht unlogisch oder falsch, aber eben -immer
> definiert-.

Anstatt Bugs/Pfusch zu verstecken, könnte (sollte!) man das Programm 
hier einfach kontrolliert abstürzen lassen.

Autor: x^y (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael B. schrieb:
> memcmp fehlt die Länge, und strcmp wäre passender, und schon lange gibt
> es lstrcmp

strcmp() war hier gemeint, Danke

Autor: x^y (Gast)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Jemand schrieb:
> Anstatt Bugs/Pfusch zu verstecken, könnte (sollte!) man das Programm
> hier einfach kontrolliert abstürzen lassen.

Und wie genau willst du das sicherstellen?

Autor: Jörg W. (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
1 lesenswert
nicht lesenswert
x^y schrieb:
> Jemand schrieb:
>> Anstatt Bugs/Pfusch zu verstecken, könnte (sollte!) man das Programm
>> hier einfach kontrolliert abstürzen lassen.
>
> Und wie genau willst du das sicherstellen?

Indem Zugriff auf einen Nullpointer halt eine Exception wirft.

Aber wir sind jetzt schon ziemlich weit weg vom Ursprungsthema. :)

Autor: gcc 10.1 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. S. schrieb:

> Für den TO musst Du aber noch dazu sagen, dass aus eine LIB nur genau
> die Einheiten ("~C-Files~") dazu gelinkt werden, die gebraucht werden.

Mit funktionierender LTO kann es durchaus sein dass nur ein kleiner Teil 
vom Code einer Lib/funktion.c im Binary landet..

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael B. schrieb:
> und dann überlege, ob dein Compiler aus
>
> https://github.com/gcc-mirror/gcc/blob/master/libgcc/memcpy.c
>
> dasselbe macht.

Dann aber bitte nicht Äpfel mit Birnen vergleichen; hier zum Beispiel 
Implementierungen der Newlib

Armv7a (ca 500 Zeilen Assembler):
http://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;a=blob;f=newlib/libc/machine/arm/memcpy-armv7a.S;h=cd7962e075a30cb90ec073d77b177c3536429b9b;hb=HEAD

x86_64:
http://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;a=blob;f=newlib/libc/machine/x86_64/memcpy.S;h=81dd0c4235001521a16af5dbfbdebbcec5f85daa;hb=HEAD

Die Public Domain Immplementierung beim GCC dient i.W. um in der 
Entwicklungsphase ein memcpy in der libgcc zu haben, um den Compiler 
(besser) testen zu können, da GCC memcmp / memset erzeugen kann, auch 
wenn dies nicht explizit in der Quelle steht.

In der endgültigen Toolchain wird man in der libc eine auf die Maschine 
optimierte Version haben (wollen), wie in avr-libc oder den obigen 
Beispielen aus der Newlib.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.