Vorsicht mit Arrayindices

Für alles, was in den übrigen Lazarusthemen keinen Platz, aber mit Lazarus zutun hat.

Re: Vorsicht mit Arrayindices

Beitragvon Mathias » 11. Apr 2018, 15:34 Re: Vorsicht mit Arrayindices

Und warum zum Henker sollte ich range checks ausschalten?

Aus Geschwindigkeitsgründen, jede Überprüfung kostet Zeit.

Was bis jetzt geschrieben wurde, ist noch alles harmlos, man kann auch Array negativ deklarieren.
Code: Alles auswählen
var
  a0: array[-10.. -5] of byte;
  a1: array[-10..5] of byte;


Wen man bei 0 beginnt hat man den Vorteil, der Zugriff ist immer gleich, egal ob die Array dynamisch oder statisch ist.
Wen man eine Array lokal in einer Procedure verwendet, dann ist es nicht so tragisch, wen sie nicht bei 0 beginnt, aber bei systemweiten Sachen ist es aber von Vorteil mit 0 zu beginnen.
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 4342
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon m.fuchs » 11. Apr 2018, 16:19 Re: Vorsicht mit Arrayindices

Mathias hat geschrieben:
Und warum zum Henker sollte ich range checks ausschalten?

Aus Geschwindigkeitsgründen, jede Überprüfung kostet Zeit.

Ich wiederhole mich solange bis es angekommen ist: Unittests, Unittests, Unittests! Und zwar mit allen Checks.
Da kommt es dann auf die Zeitverzögerungen der Prüfungen nicht an und sorgt für einen funktionierenden Code.

All diese Probleme die hier geschildert werden, habe nichts mit dem nicht-0-basiertem Index zu tun. Dass ich irgendwo hinschreibe, wo ich nicht hinschreiben soll kann mir auch so passieren. Und eben darum sichert man das ab.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de
m.fuchs
 
Beiträge: 1972
Registriert: 22. Sep 2006, 18:32
Wohnort: Berlin
OS, Lazarus, FPC: Winux (L 1.8.4, FPC 3.0.4) | 
CPU-Target: x86, x64, arm
Nach oben

Beitragvon Warf » 11. Apr 2018, 17:21 Re: Vorsicht mit Arrayindices

m.fuchs hat geschrieben:Ich wiederhole mich solange bis es angekommen ist: Unittests, Unittests, Unittests! Und zwar mit allen Checks.
Da kommt es dann auf die Zeitverzögerungen der Prüfungen nicht an und sorgt für einen funktionierenden Code.

All diese Probleme die hier geschildert werden, habe nichts mit dem nicht-0-basiertem Index zu tun. Dass ich irgendwo hinschreibe, wo ich nicht hinschreiben soll kann mir auch so passieren. Und eben darum sichert man das ab.


Dagegen sage ich ja nichts, aber du hast meine prämisse falsch verstanden. Man muss davon ausgehen das bei einem größeren Projekt irgendwann es zwangsläufig passiert das jemand mit for i:=0 to Length(arr)-1 durch einen array iteriert. Das viele eventuell drüber iterieren weil sie das -1 weglassen gibt es zwar auch, aber danach lässt sich sehr einfach finden. Dafür muss man den Code nicht verstanden haben, jedem Programmierer egal ob java, Pascal oder C würde bei der zeile for i:=0 to Length(arr) do die arlamglocken läuten, während for i:=0 to Length(arr)-1 auf den ersten blick korrekt aussieht und man muss überall die datentypen überprüfen was deutlich mehr aufwand ist. Und Testsuites sind niemals vollständig, selbst die seit jahrzehnten gepflegte CoreUtils Test suite coverd nur 80% des Codes. Das muss nur eine kleine For schleife sein die von den Tests nicht abgedeckt wird und irgendwann knallt es

Wenn man alle Arrays mit 0 beginnen lässt schließt man eine komplette semantische Fehlerklasse aus. Man könnte meinetwegen auch alle arrays mit 1 oder -45 anfangen lassen, dann ist es aber nicht mit den Dynamischen Arrays konsistent
Warf
 
Beiträge: 985
Registriert: 23. Sep 2014, 16:46
Wohnort: Aachen
OS, Lazarus, FPC: Mac OSX 10.11 | Win 10 | FPC 3.0.0 | L trunk | 
CPU-Target: x86_64, i368, ARM
Nach oben

Beitragvon m.fuchs » 11. Apr 2018, 18:02 Re: Vorsicht mit Arrayindices

Warf hat geschrieben:Man muss davon ausgehen das bei einem größeren Projekt irgendwann es zwangsläufig passiert das jemand mit for i:=0 to Length(arr)-1 durch einen array iteriert.


Warum muss man davon ausgehen? Den Code für die Iterieration schreibt der Entwickler der das Array angelegt hat. Wenn jemand den Code für die Iteration ändert, dann macht er das ja nur weil er auch die Arraygrenzen ändert. Oder umgekehrt.

Sinnvoller als die Forderung nur Arrays mit Startindex 0 zu verwenden wäre es doch die ausschließlich Verwendung von Low und High zu fordern. Das beseitigt alle Probleme.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de
m.fuchs
 
Beiträge: 1972
Registriert: 22. Sep 2006, 18:32
Wohnort: Berlin
OS, Lazarus, FPC: Winux (L 1.8.4, FPC 3.0.4) | 
CPU-Target: x86, x64, arm
Nach oben

Beitragvon kupferstecher » 11. Apr 2018, 19:39 Re: Vorsicht mit Arrayindices

siro hat geschrieben:Ich hab in meinem ganzen Leben noch kein Array gehabt, was nicht bei 0 angefangen hat.

Eigentlich braucht man fast nie ein bei null beginnendes Array, das -1 zeigt ja auch, dass der Nullindex unnatürlich ist. In C ist das anders, dort muss (musste?) man ja Arrays selbst verwalten. Da dynamische Arrays aber in FreePascal immer bei null anfangen, verwende ich das auch bei statischen Arrays meistens.

Warf hat geschrieben:während for i:=0 to Length(arr)-1 auf den ersten blick korrekt aussieht und [...]

Der Fehler kann ja auch innerhalb der Schleife liegen. Beispiel:
Code: Alles auswählen
for ii:= 0 to length(arr)-1 
 do arr[ii]:= arr[ii]+ arr[ii+1]

Das passiert besonders leicht, wenn man versucht eine Schleife auf null zu 'biegen', die natürlicherweise andere Grenzen hätte.

Es gibt übrigens einen Wikiartikel zu diesem Thema (in Englisch):
http://wiki.freepascal.org/Defensive_pr ... techniques
kupferstecher
 
Beiträge: 168
Registriert: 17. Nov 2016, 11:52

Beitragvon Socke » 11. Apr 2018, 20:29 Re: Vorsicht mit Arrayindices

kupferstecher hat geschrieben:Es gibt übrigens einen Wikiartikel zu diesem Thema (in Englisch):
http://wiki.freepascal.org/Defensive_pr ... techniques

Dass man mit einem Set über einen Range-Index iterieren kann, wusste ich noch nicht. Interessantes Feature!
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Socke
 
Beiträge: 2557
Registriert: 22. Jul 2008, 18:27
Wohnort: Köln
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 8.1/Debian GNU/Linux/Raspbian/openSUSE | 
CPU-Target: 32bit x86 armhf
Nach oben

Beitragvon Mathias » 11. Apr 2018, 21:00 Re: Vorsicht mit Arrayindices

Dass man mit einem Set über einen Range-Index iterieren kann, wusste ich noch nicht. Interessantes Feature!

Dann gucke mal die Deklaration von TColor, TGraphicsColor an.
Code: Alles auswählen
  TGraphicsColor = -$7FFFFFFF-1..$7FFFFFFF;

Selbst habe ich sowas noch nie gebraucht.
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 4342
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon marcov » 13. Apr 2018, 10:40 Re: Vorsicht mit Arrayindices

Code: Alles auswählen
 
 for i:=low(fsomearray) to high(fsomearray) do
 ...


oder

Code: Alles auswählen
 
var x : integer; // element typ.
 for x in fsomearray do
 ...
marcov
 
Beiträge: 1035
Registriert: 5. Aug 2008, 08:37
Wohnort: Eindhoven (Niederlande)
OS, Lazarus, FPC: Windows ,Linux,FreeBSD,Dos (L trunk FPC trunk) | 
CPU-Target: 32/64,PPC(+64), ARM
Nach oben

Beitragvon Warf » 13. Apr 2018, 12:19 Re: Vorsicht mit Arrayindices

kupferstecher hat geschrieben:
siro hat geschrieben:Ich hab in meinem ganzen Leben noch kein Array gehabt, was nicht bei 0 angefangen hat.

Eigentlich braucht man fast nie ein bei null beginnendes Array, das -1 zeigt ja auch, dass der Nullindex unnatürlich ist. In C ist das anders, dort muss (musste?) man ja Arrays selbst verwalten. Da dynamische Arrays aber in FreePascal immer bei null anfangen, verwende ich das auch bei statischen Arrays meistens.

Der Fehler kann ja auch innerhalb der Schleife liegen. Beispiel:
Code: Alles auswählen
for ii:= 0 to length(arr)-1 
 do arr[ii]:= arr[ii]+ arr[ii+1]

Das passiert besonders leicht, wenn man versucht eine Schleife auf null zu 'biegen', die natürlicherweise andere Grenzen hätte.

Es gibt übrigens einen Wikiartikel zu diesem Thema (in Englisch):
http://wiki.freepascal.org/Defensive_pr ... techniques



Das der Fehler auch in der Schleife liegen kann tut aber nichts zur Sache

EDIT: missverstanden
Zuletzt geändert von Warf am 15. Apr 2018, 21:17, insgesamt 1-mal geändert.
Warf
 
Beiträge: 985
Registriert: 23. Sep 2014, 16:46
Wohnort: Aachen
OS, Lazarus, FPC: Mac OSX 10.11 | Win 10 | FPC 3.0.0 | L trunk | 
CPU-Target: x86_64, i368, ARM
Nach oben

Beitragvon Timm Thaler » 13. Apr 2018, 13:09 Re: Vorsicht mit Arrayindices

Nur dass Du hier ein Problem konstruierst, welches so nicht existiert - oder nur in den Köpfen von eingefleischten C-Programmierern, die es nicht anders können.

Als ich meine Heizungssteuerung von C auf Pascal umgeschrieben habe, war ich froh endlich sinnvolle Array definieren zu können und nicht ständig zwischen Kanal 1..24 auf Arrayindex 0..23 und umgekehrt hin und herrechnen zu müssen. Das ist nicht weniger fehlerträchtig. Natürlich kann ich alle Kanäle von 0 anfangen lassen, aber ich verwende eine Hochsprache ja genau deswegen, damit sie mir das erspart, sonst kann ich gleich Assembler schreiben.

Und Arraygrenzen muss ich sowieso abfragen: Wenn über die RS232 die Anfrage kommt, sende mir den Wert von Kanal N, und N ist fälschlicherweise Null, dann ist bei dec(N) der Index auf ein Nullbasiertes Array genauso falsch wie ohne dec auf ein 1-basiertes. Ich muss also sinnigerweise immer obere und untere Arraygrenze prüfen.

Sinnvoll ist ein Nullbasiertes Array z.B. für einen Ringbuffer, wo man mit mod length für Operationen über den Buffer (gleitender Mittelwert...) immer schön im Bereich bleiben kann.
Timm Thaler
 
Beiträge: 730
Registriert: 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded | 
CPU-Target: Raspberry Pi 3
Nach oben

Beitragvon kupferstecher » 13. Apr 2018, 17:59 Re: Vorsicht mit Arrayindices

Warf hat geschrieben:Das der Fehler auch in der Schleife liegen kann tut aber nichts zur Sache

Diese Art der Argumentation [...]

Das hättest du dir sparen können, erstmal die Argumente verstehen heißt die Devise.

Ein Beharren auf nullbasierte Schleifen erzwingt gegebenenfalls Umrechnungen innerhalb der Schleife, die genau für die besprochenen Bereichsüberschreitungen gefährdet sind. Auf dein E-Auto Beispiel bezogen: Du tust so als wäre die Stromerzeugung emissionslos.

Natürlich sollte man einen Standard für sich finden (durch die Nullbasierung bei dynamischen Schleifen ist der Standard vorgegeben), aber je nach konkreter Situation sollte man davon auch abweichen.
kupferstecher
 
Beiträge: 168
Registriert: 17. Nov 2016, 11:52

Beitragvon Warf » 13. Apr 2018, 19:12 Re: Vorsicht mit Arrayindices

kupferstecher hat geschrieben:Das hättest du dir sparen können, erstmal die Argumente verstehen heißt die Devise.

Ein Beharren auf nullbasierte Schleifen erzwingt gegebenenfalls Umrechnungen innerhalb der Schleife, die genau für die besprochenen Bereichsüberschreitungen gefährdet sind. Auf dein E-Auto Beispiel bezogen: Du tust so als wäre die Stromerzeugung emissionslos.

Natürlich sollte man einen Standard für sich finden (durch die Nullbasierung bei dynamischen Schleifen ist der Standard vorgegeben), aber je nach konkreter Situation sollte man davon auch abweichen.


Ah sorry, hab dein beispiel auch nicht richtig verstanden, hatte irgendwie was ganz anderes im kopf
Warf
 
Beiträge: 985
Registriert: 23. Sep 2014, 16:46
Wohnort: Aachen
OS, Lazarus, FPC: Mac OSX 10.11 | Win 10 | FPC 3.0.0 | L trunk | 
CPU-Target: x86_64, i368, ARM
Nach oben

• Themenende •
Vorherige

Zurück zu Sonstiges



Wer ist online?

Mitglieder in diesem Forum: Google [Bot], TSchnuckenbock und 4 Gäste

porpoises-institution
accuracy-worried