Arrays und Pointer Problem



  • Ich durchsuche Arrays bisher via Pointer-Incrementierung und nicht mit Indices. Folgender Code wurde korrekterweise vom BoundChecker bemängelt, obwohl ich das Problem nie selbst entdeckt hätte.

    int list[SIZE];
    
    for (int * current = list; current < list + SIZE; current++) *current = foo(); // Warning
    

    Ist dieser "Fehler" problematisch? Wenn ja, dann habe ich nur zwei Möglichkeiten ihn zu beheben.

    1.

    int list[SIZE];
    
    for (int * current = list; current <= list + SIZE - 1; current++) *current = foo(); // Ok
    

    2.

    int list[SIZE];
    
    for (int current = 0; current < SIZE; current++) list[current] = foo(); // Ok
    

    Welche Alternativen (ohne die Size der Table um 1 zu erhöhen) gibt es noch, und ist diese Warnung wirklich problematisch oder "unsauber"?

    Gruss
    T.



  • Hallo Tomahawk,

    ich kann keinen Fehler in dem ersten code entdecken:

    int list[SIZE];
    
    for (int * current = list; current < list + SIZE; current++) *current = foo(); // Warning
    

    Was genau gibt der "BoundChecker" denn aus ? Konjunktive ?

    Ich habe schonmal 'lint' verwendet. Das Potential dieser statischen Code Analyser ist zwar toll aber, es wurden zu viele Warnungen in schon existierendem Code generiert.
    Zu oft waren diese Warnungen nach näherem Betrachen dann doch keine Fehler.
    Zwar kann man die Warnungen in der Regel auch abschalten,
    aber dann macht so ein Tool ja auch keinen Sinn mehr ...

    Schade eigentlich, hoffentlich werden die Tools besser,
    insbesondere das Verhältnis echter Fehler zu Meldungen:

    Gruß Frank



  • Fakt ist, dass Code Nummer 2 viel sauberer und angenehmer zu lesen ist. Warum machst du mit rohen Zeigern rum, wenn du auch mit dem [] Operator darauf zugreifen kannst? Das ist doch viel intuitiver.



  • llllllllll schrieb:

    Das ist doch viel intuitiver.

    Sieht hübscher aus, aber wenn Du den ASM- Output anguckst, wirst Du feststellen, daß der Code mit dem rohen Pointer ein Quentchen schneller ist. Tomahawk ist obendrein Speedfuchser ... 😉



  • So sieht das aus:

    int list[2];
    
    int * b = list + 2;  // hier wird b eine Speicherstelle zugewiesen, die ausserhalb des Bereichs von "list" liegt
    
    for (int * a = list; a < b; a++)
    

    Gruss
    T.



  • pointercrash() schrieb:

    llllllllll schrieb:

    Das ist doch viel intuitiver.

    Sieht hübscher aus, aber wenn Du den ASM- Output anguckst, wirst Du feststellen, daß der Code mit dem rohen Pointer ein Quentchen schneller ist. Tomahawk ist obendrein Speedfuchser ... 😉

    Das ist so vernachlässigbar und je nach Compiler eh unterschiedlich. Letztendlich bringts nichts - außer Ärger. 😃



  • llllllllll schrieb:

    Das ist so vernachlässigbar und je nach Compiler eh unterschiedlich. Letztendlich bringts nichts - außer Ärger. 😃

    Nö, guck's an. Das nackte Konstrukt legt fast im zweistelligen Prozentbereich zu, auf allen Compilern, auf denen ich mir das angeguckt habe.
    Natürlich kann das auf Promillebereiche schwinden in Bezug auf die Gesamtapplikation und ob man die Übersichtlichkeit dafür opfern mag, ist jedermanns eigene Entscheidung.
    Aber Tomahawk ist schon sehr auf Speed aus ... 😉



  • pointercrash() schrieb:

    llllllllll schrieb:

    Das ist so vernachlässigbar und je nach Compiler eh unterschiedlich. Letztendlich bringts nichts - außer Ärger. 😃

    Nö, guck's an. Das nackte Konstrukt legt fast im zweistelligen Prozentbereich zu, auf allen Compilern, auf denen ich mir das angeguckt habe.
    Natürlich kann das auf Promillebereiche schwinden in Bezug auf die Gesamtapplikation und ob man die Übersichtlichkeit dafür opfern mag, ist jedermanns eigene Entscheidung.
    Aber Tomahawk ist schon sehr auf Speed aus ... 😉

    Das führt dann zwangsläufig zum "pointercrash" 😉

    Aber mal im Ernst, hier gibts tatsächlich Probleme:

    int list[2]; 
    
    int * b = list + 2;  // hier wird b eine Speicherstelle zugewiesen, die ausserhalb des Bereichs von "list" liegt 
    
    for (int * a = list; a < b; a++)
    

    Und davon hat mein Programm jetzt einige, die ich step-by-step beheben muss. Aber wenn sich der Speed-Tradeoff in Grenzen hält, baue ich wieder zu arrays mit Indices zurück.

    Gruss
    T.



  • Nachtrag:

    Die Fehlermeldung vom BoundsChecker ist:

    Pointer Error:
    As a result of pointer arithmetic, the pointer 0x0051AC30 is out of range; no longer within the buffer for variable list [...]
    *

    Gruss
    T.



  • Hallo Tomahawk,

    Jetzt habe ich auch die "Fehlermeldung" verstanden.

    int list[SIZE];
    
    for (int * current = list; current < list + SIZE; current++) *current = foo(); // Warning
    

    Nach dem Verlassen der Schleife steht current genau ein Element hinter der Liste.
    Also current ist "out of range".

    Schön das BoundsChecker das erkennt,
    aber dein Code greift nicht auf das Element zu,
    also kein Fehler und auch nicht 'unsauber',
    nur eine falsche und irritierende Meldung.

    Dein 1. Vorschlag löst das Problem.

    int list[SIZE];
    
    for (int * current = list; current <= list + SIZE - 1; current++) *current = foo(); // Ok
    

    Wenn SIZE statisch ist würde ich diese Variante nehmen.
    Wenn SIZE dynamisch ist, würde ich am code nichts ändern.
    Jedoch einen Kommentar einfügen,
    bei dem BoundsChecker warscheinlich nicht gut abschneiden würde ...

    Viel Erfolg, Gruß Frank


Log in to reply