Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

30.08.2015, 17:53

[C++] - Objekte aus einem Feld(Array) haben untereinander unerwünschten Zugriff ?!

Hallo,

ich verwende derzeit für meine Animationen eine Art Warteschleife. Also ein array, welches objecte des Typus "Animation" hält. Jedes Objekt natürlich mit eigenen Daten.
Funktionert bis auf eine Ausnahme auch gut: scheinbar haben die Variablen eines Objektes auswirkungen auf die eines Anderen. 8| ?(

So zum Beispiel gibt es die bool variable "first" die bei erstellung mit true initalisiert wird. in einer Funktion wird sie dann auf false gesetzt und nicht mehr berüht.
In einer nächsten Animation, welche also ein völlig neues object ist, ist diese variable dann plötzlich schon initialisiert.

Die alte Animation wurde dann bereits entfernt.
Die Variablen sind alle static. Ich weiß zwar das, es das Problem lösen würde sie non-static zu machen, aber das geht zu sehr auf die performance.

Deshalb meine Frage : weiß irgendwer warum das passiert und wie ich das vermeiden kann ?

2

30.08.2015, 18:23

Poste doch bitte den Code, sonst kann dir keiner helfen.
Cube Universe
Entdecke fremde Welten auf deiner epischen Reise durchs Universum.

3

30.08.2015, 18:41

Poste doch bitte den Code, sonst kann dir keiner helfen.
Hm .. welchen Teil vom Code?

Hier werden die Animationen verwaltet :

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void GI::update()
{
    for (int i = 0; i < objectCount; i++)
    {
        if (objectBuffer[i]->animationCount > 0)
        {
            static short result;
            objectBuffer[i]->animationList[0]->preUpdate(&objectBuffer[i]->positionX, &objectBuffer[i]->positionY, &objectBuffer[i]->positionZ, &objectBuffer[i]->rotationX, &objectBuffer[i]->rotationY, &objectBuffer[i]->rotationZ);
            if ((result = objectBuffer[i]->animationList[0]->play()) == -1) continue;
            objectBuffer[i]->animationList[0]->postUpdate(&objectBuffer[i]->positionX, &objectBuffer[i]->positionY, &objectBuffer[i]->positionZ, &objectBuffer[i]->rotationX, &objectBuffer[i]->rotationY, &objectBuffer[i]->rotationZ);

            if (result == 1)
            {
                objectBuffer[i]->animationList[0]->deinitialize();
                removeAnimationFromQueue(i);
            }

        }
    }
}


Hier die Animation selbst :

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
bool Animation::translateRotate()
{

    static int tick = 0;;
    static bool first = true;
    static float rotationSpeedX = 0.0F, rotationSpeedY = 0.0F, rotationSpeedZ = 0.0F;
    static float speedX = 0.0F, speedY = 0.0F, speedZ = 0.0F;
    static bool negativeX = false, negativeY = false, negativeZ = false;

    

    if (first)
    {
        first = false;

        tick = 0;
        rotationSpeedX = 0.0F;
        rotationSpeedY = 0.0F;
        rotationSpeedZ = 0.0F;
        speedX = 0.0F;
        speedY = 0.0F;
        speedZ = 0.0F;
        negativeX = false;
        negativeY = false;
        negativeZ = false;

        float distance = 0.0F, hypo1 = 0.0F;
        double hypo2 = 0.0F;
        float distanceX = 0.0F, distanceY = 0.0F, distanceZ = 0.0F, ticks = 0.0F;

        originCoordX > destCoordX ? distanceX = originCoordX - destCoordX : distanceX = destCoordX - originCoordX;
        originCoordY > destCoordY ? distanceY = originCoordY - destCoordY : distanceY = destCoordY - originCoordY;
        originCoordZ > destCoordZ ? distanceZ = originCoordZ - destCoordZ : distanceZ = destCoordZ - originCoordZ;

        hypo1 = (distanceX * distanceX) + (distanceY * distanceY);

        hypo2 = ((double)(hypo1 + (distanceZ * distanceZ)));

        hypo2 = sqrt(hypo2);

        distance = (float)hypo2;

        ticks = distance / speed;

        speedX = distanceX / ticks;
        speedY = distanceY / ticks;
        speedZ = distanceZ / ticks;

        if (destRotX < 0)
        {
            negativeX = true;
            destRotX = -destRotX;
        }

        if (destRotY < 0)
        {
            negativeY = true;
            destRotY = -destRotY;
        }

        if (destRotZ < 0)
        {
            negativeZ = true;
            destRotZ = -destRotZ;
        }

        if (destRotX != 0) rotationSpeedX = destRotX / ticks;
        else rotationSpeedX = 0;
        if (destRotY != 0) rotationSpeedY = destRotY / ticks;
        else rotationSpeedY = 0;
        if (destRotZ != 0) rotationSpeedZ = destRotZ / ticks;
        else rotationSpeedZ = 0;



        

        tick = (int)ticks;

    }

    

    if (tick > 0)
    {
        
        ...mathematik
        (variablen werden neu berechnet)
        
        tick--;

        return 0;
    }
    else
    {

        ...unrelevantes zeug...
        
        
        first = true;
        return 1;
    }

}


Animationsklasse:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#ifndef ANIMATION_H_
#define ANIMATION_H_

#include <string.h>
#include <math.h>

#define ANIMATION_TRANSLATESMOOTH 1
#define ANIMATION_ROTATESMOOTH 2
#define ANIMATION_TRANSLATEROTATE 3

class Animation
{

    public:

        Animation();
        Animation(const Animation& other);
        ~Animation();

        float originCoordX, originCoordY, originCoordZ;
        float destCoordX, destCoordY, destCoordZ;
        float finalCoordX, finalCoordY, finalCoordZ;

        float originRotX, originRotY, originRotZ;
        float destRotX, destRotY, destRotZ;
        float finalRotX, finalRotY, finalRotZ;

        float angle, radius;

        float speed;

        int type;

        //FUNCTIONS

        int play();

        void setUnused();

        void preUpdate(float *originPositionX, float *originPositionY, float *originPositionZ, float *originRotationX, float *originRotationY, float *originRotationZ);
        void postUpdate(float *newPositionX, float *newPositionY, float *newPositionZ, float *newRotationX, float *newRotationY, float *newRotationZ);
        void deinitialize();
        
        bool translateSmooth();
        bool rotateSmooth();
        bool translateRotate();

    private:

};

#endif


Was wäre noch wichtig?

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

4

30.08.2015, 19:08

Du hast es selbst schon gesagt. Die Variable darf nicht static sein. Normalerweise sind Variablen in einer Klasse einer bestimmten Instanz zugeordnet. Das bedeutet wenn du eine Klasse mit einer nicht statischen Variable hast und zwei verschiedene Instanzen der Klasse anlegst, dann hat jede Instanz ihre eigene Version der Variable. Innerhalb der verschiedenen Instanz können die Variablen unterschiedliche Werte speichern.
Eine statische Variable ist nicht einer Instanz einer Klasse zugeordnet sondern der Klasse selbst. Legst du zwei Instanzen deiner Klasse an und änderst in der einen den Wert der Variable so wird der Wert in allen Instanzen der Klasse geändert. Die Instanzen teilen sich quasi die selbe Variable.
Für dein Problem bedeutet das also dass du die Variable nicht statisch machen darfst. Mit Performance hat das auch wenig zu tun. Bei einer nicht statischen Variable besitzt eben jede Instanz ihre eigene Version der Variable. Dadurch verbraucht dein Programm dann etwas mehr Speicher. static ist allgemein ein Schlüsselwort was du vermutlich relativ selten benötigen wirst. Als ich angefangen habe kannte ich static gar nicht und habe es auch lange nicht vermisst. Aber static hat natürlich seine Berechtigung und wird auch immer mal wieder benötigt, bzw kann dir Code vereinfachen. In deinem Fall ist es aber falsch.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

5

30.08.2015, 19:23

Du hast es selbst schon gesagt. Die Variable darf nicht static sein. Normalerweise sind Variablen in einer Klasse einer bestimmten Instanz zugeordnet. Das bedeutet wenn du eine Klasse mit einer nicht statischen Variable hast und zwei verschiedene Instanzen der Klasse anlegst, dann hat jede Instanz ihre eigene Version der Variable. Innerhalb der verschiedenen Instanz können die Variablen unterschiedliche Werte speichern.
Eine statische Variable ist nicht einer Instanz einer Klasse zugeordnet sondern der Klasse selbst. Legst du zwei Instanzen deiner Klasse an und änderst in der einen den Wert der Variable so wird der Wert in allen Instanzen der Klasse geändert. Die Instanzen teilen sich quasi die selbe Variable.
Für dein Problem bedeutet das also dass du die Variable nicht statisch machen darfst. Mit Performance hat das auch wenig zu tun. Bei einer nicht statischen Variable besitzt eben jede Instanz ihre eigene Version der Variable. Dadurch verbraucht dein Programm dann etwas mehr Speicher. static ist allgemein ein Schlüsselwort was du vermutlich relativ selten benötigen wirst. Als ich angefangen habe kannte ich static gar nicht und habe es auch lange nicht vermisst. Aber static hat natürlich seine Berechtigung und wird auch immer mal wieder benötigt, bzw kann dir Code vereinfachen. In deinem Fall ist es aber falsch.
Danke für deine schnelle Antwort.
Damit hast du meine vermutung bestätigt. Die Klassen teilen sich die Variable.
Zu der performance: Ich habe zu Zeiten gelernt, dass eine static Variable nicht im RAM sondern auf der Festplatte angelegt wird. Wenn ich jetzt also 5 mal pro tick ein Haufen Variablen im RAM neu zuordne, ist das sehr ineffizient. Als Lösung : static, sorgt dafür das die Variable nicht neuerstellt wird, sie bleibt bestehen und das bringt in dem Fall eine bessere performance.
Deswegen habe ich nach einer alternative gesucht.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

6

30.08.2015, 19:32

Ich habe zu Zeiten gelernt, dass eine static Variable nicht im RAM sondern auf der Festplatte angelegt wird.
Wo auch immer Du das gelernt hast, es ist falsch.
Static heißt lediglich, dass alle Instanzen einer Klasse sich diese Variable teilen, weil es eine Klassen-Variable und keine Instanz-Variable ist. Mit der Festplatte hat das nichts zu tun und das wäre auch ganz übel, weil Zugriffe auf die Festplatte um etwa den Faktor 10.000 langsamer sind als Zugriffe auf den RAM. Neu zugeordnet wird da übrigens auch nichts "pro Tick".
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

7

30.08.2015, 20:00

Ich habe zu Zeiten gelernt, dass eine static Variable nicht im RAM sondern auf der Festplatte angelegt wird.
Wo auch immer Du das gelernt hast, es ist falsch.
Static heißt lediglich, dass alle Instanzen einer Klasse sich diese Variable teilen, weil es eine Klassen-Variable und keine Instanz-Variable ist. Mit der Festplatte hat das nichts zu tun und das wäre auch ganz übel, weil Zugriffe auf die Festplatte um etwa den Faktor 10.000 langsamer sind als Zugriffe auf den RAM. Neu zugeordnet wird da übrigens auch nichts "pro Tick".
Autovariablen haben local scope und werden nach verlassen ihres scopes gelöscht.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

8

30.08.2015, 20:16

Über auto hat doch gar keiner geredet?
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

9

30.08.2015, 20:25

Und du meinst lokale Variablen. Hier geht es um Membervarialen von Klassen. Die werden gelöscht wenn die Instanz der Klasse gelöscht wird. Was du über den Zugriff auf den RAM bzw auf die Festplatte geschrieben hast ist wie BlueCobold schon geschrieben hat auch quatsch. Vor allem ist es der Zugriff auf den RAM der viel viel schneller ist.
Ich weiß nicht mit welchem Buch du lernst bzw mit welchen Unterlagen aber wenn du da solche Informationen raus ziehst solltest du die dringend wechseln. Das hat jemand geschrieben der nicht nur keine Ahnung hat sondern auch eine ziemliche merkwürdige Phantasie.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

10

31.08.2015, 04:43

Also meine Festplatte schafft 200 MB/s, der RAM nur 51,2 GB/s (Speicherbandbreite laut Prozessorspezifikation). Wie jemand auf die Idee kommt, dass der RAM langsamer ist, weiß ich auch nicht.

Lokale Variablen werden auf dem Stack erzeugt, dazu wird einfach ein Stackpointer-Register verändert, was direkt im Prozessor ist, der Zugriff auf die Variablen erfolgt dann über Lesen und Schreiben an der Adresse Stackpointer + Offset im RAM, sehr wahrscheinlich auch direkt im L1 Cache, der deutlich schneller als der RAM ist. Nachdem der Scope der Variablen verlassen wird (nach dem {...} Block, in dem die Variablen stehen, bzw. nach dem return in der Funktion), wird der Stackpointer wieder auf den vorherigen Wert zurückgesetzt. Das ist überhaupt nicht ineffizient.
Cube Universe
Entdecke fremde Welten auf deiner epischen Reise durchs Universum.

Werbeanzeige