Avatar billede emmek Nybegynder
11. marts 2004 - 18:33 Der er 4 kommentarer og
1 løsning

Enkelt-kædet liste..

Hejsa!

Jeg har et problem, da en klasse jeg er ved at skrive dumper core, relativt sent inde i forløbet.

Kodeordene er effektivitet og hukommelsesbesparelse.
Det er også derfor jeg har fravalgt stl's list, da den er dobbelt-kædet (jeg ikke har brug for at bevæge mig baglæns i listen og koster exstra CPU og MEM).

Det er også derfor jeg 'gør alt' i en og samme funktion.

Listen indeholder nogle tids-stempler (returneret fra time(0)), og listen skal så indeholde tidsstempler for en vis periode.
(this->timespan måles i sekunder). Når man vil indsætte nye tidsstempler, kan man opdatere det interne 'ur' i klassen (this->updateStamp), og det er meningen er så at indsættelses funktionen så skal rydde op i listen, og smide tidsstempler væk der er blevet for gamle efter opdateringen af det interne ur.

Efter at listen er blevet bladret helt til ende, og for gamle tidsstempler er blevet fjernet, indsættes de nye. Til sidst returneres hvor mange stempler listen resulterende indeholder.

Her er koden:
int OutcomeNode::insertCleanAndCount(unsigned int newUpdateStamp,
                int measuringCount, unsigned int *measuringArray)
{
    if(newUpdateStamp < this->updateStamp)
    {
        InvalidArgException ex;
        ex.setLocation((IObject *)this, "insertCleanAndCount(unsigned int newUpdateStamp, int measuringCount, unsigned int *measuringArray)");
        stringstream descr;
        descr << "Attempt to update the updateStamp to something older.\nupdateStamp = "
            << this->updateStamp << " and newUpdateStamp = " << newUpdateStamp
            << " in OutcomeNode[" << this->outcomeStartUs << ":"
            << this->outcomeEndUs << "].";
        ex.setDescription(descr.str());
        throw ex;
    }
           
   
    this->updateStamp = newUpdateStamp;
   
    int obsoleteStamp = (this->updateStamp - this->timespan);
    int obsoleteHourStamp = (this->updateStamp - 3600);
   
    this->lastHourCount = 0;            //Will be updated later on..
   
    int measuringProgress = 0;

    //Go through _ALL_ MeasureNode's and clean out old ones as new ones are added
    MeasureNode *temp = this->firstPtr, *oldTemp = 0, *newNode = 0;
    while(temp)
    {
        //First check if node should be removed.. i.e. if stamp is older then timespan ago
        while(temp && temp->timestamp < obsoleteStamp)
        {
            this->count--;
            if(temp == this->firstPtr)
            {
                this->firstPtr = temp->nextPtr;   
                delete temp;
                temp = this->firstPtr;
            }
            else
            {
                if(this->firstPtr == 0 || oldTemp == 0 || temp == 0)
                {   
                    cout << "first: " << (int)this->firstPtr << " oldTemp: " << (int)oldTemp << " temp: " << (int)temp << endl;
                    if(this->firstPtr)
                    {
                        cout << "this->firstPtr->timestamp: " << this->firstPtr->timestamp << endl;
                        cout << "this->firstPtr->nextPtr: " << (int)this->firstPtr->nextPtr << endl;
                    }
                    if(oldTemp)
                    {
                        cout << "oldTemp->timestamp: " << oldTemp->timestamp << endl;
                        cout << "oldTemp->nextPtr: " << (int)oldTemp->nextPtr << endl;
                    }
                    if(temp)
                    {
                        cout << "temp->timestamp: " << temp->timestamp << endl;
                        cout << "temp->nextPtr: " << (int)temp->nextPtr << endl;
                    }
                    sleep(2);
                }
                oldTemp->nextPtr = temp->nextPtr;    //oldTemp should be set for this scenario to work
                delete temp;
                temp = oldTemp->nextPtr;        //Moving on to next node
            }
        }
        if(temp->timestamp >= obsoleteHourStamp) this->lastHourCount++;
        oldTemp = temp;
        temp = temp->nextPtr;
    }

   
    //Insert measurings in end of list..
    while( measuringProgress < measuringCount )
    {
        //Skip too old "new" measurings
        while(measuringProgress < measuringCount &&
            measuringArray[measuringProgress] < obsoleteStamp)
        {
            measuringProgress++;
        }   
        if(measuringProgress < measuringCount)
        {
            newNode = new MeasureNode;
            newNode->timestamp = measuringArray[measuringProgress++];
            //temp will be 0 no matter what, and if firstPtr == 0, then list is empty
            if(temp == this->firstPtr) this->firstPtr = newNode;   
            else oldTemp->nextPtr = newNode;            //oldTemp should be set for this if list !empty
            newNode->nextPtr = temp;                //this should be zero
            oldTemp = newNode;
            //Increment counters
            if(newNode->timestamp >= obsoleteHourStamp) this->lastHourCount++;
            this->count++;
        }
    }
    int retval = this->count;
    return retval;
}

GNU's konsol debugger siger flg:
(gdb) bt
#0  0x080620f7 in OutcomeNode::insertCleanAndCount(unsigned, int, unsigned*) (this=0x82497c0, newUpdateStamp=0, measuringCount=0,
    measuringArray=0xbfadca14) at OutcomeNode.cpp:189
#1  0x0805c83c in MeasureSpecStats::insertMultiple(int, int, unsigned*, float*, bool) (this=0x80b7000, updateStamp=673839516, measureCount=45,
    measuretime=0xbfadc960, delay=0xbfadca20, updateStats=true) at MeasureSpecStats.cpp:419


Hvor jeg så kan fortælle at OutcomeNode.cpp:189 er afslutningen af funktionen (altså lige efter "return retval;"...)


Min egen konklusion er at jeg må gøre et eller andet forkert i listen siden at det bare lige pludselig dør for mig. Sagen er nemlig den, at hvis jeg erstatter min egen liste med en std liste, så virker alt uden problemer. Det er også derfor at jeg mener at det må være min liste der er 'syg'.

/Steffen
Avatar billede emmek Nybegynder
11. marts 2004 - 19:29 #1
Hmm har lige luret at der måske alligevel er en enkelt-kædet STL liste (slist) som jo så nok kan bruges med fordel..

Undersøger det lige, men jeg vil stadig gerne have at i kigger på ovenstående - det er sq skidt hvis man ikke kan lave sin egen kædet liste..
Avatar billede jakobroland Nybegynder
12. marts 2004 - 16:43 #2
Fejlbeskrivelsen (coredump ved return) tyder på at du har fået overskrevet returadressen på stakken, dvs. fejlen er opstået .

Jeg har prøvet din kode, men kan ikke umiddelbart få den til at fejle. Kan du poste et minimalt eksempel der trigger fejlen? Hvilken compiler bruger du?
Avatar billede emmek Nybegynder
12. marts 2004 - 17:29 #3
Det der med det minimale setup kan jeg nok ikke umiddelbart give dig..
sltnxq3# gcc -v
Using built-in specs.
Configured with: FreeBSD/i386 system compiler
Thread model: posix
gcc version 3.3.3 [FreeBSD] 20031106

Den er forholdsvis ny, men jeg tror ikke helt på at det er her den ligger..

Men det ligner også, at hvad end det nu er der smadrer stakken, så gøres det allerede inden kaldet til insertCleanAndCount, fordi den kaldes med newUpdateStamp=0, og det er i hvert fald ikke hensigten.
envidere burde der også blive kastet exception i starten, hvis den rent faktisk er 0..
    if(newUpdateStamp < this->updateStamp)
    {
        InvalidArgException ex;
        ex.setLocation((IObject *)this, "insertCleanAndCount(unsigned int newUpdateStamp, int measuringCount, unsigned int *measuringArray)");
        stringstream descr;
        descr << "Attempt to update the updateStamp to something older.\nupdateStamp = "
            << this->updateStamp << " and newUpdateStamp = " << newUpdateStamp
            << " in OutcomeNode[" << this->outcomeStartUs << ":"
            << this->outcomeEndUs << "].";
        ex.setDescription(descr.str());
        throw ex;
    }

Her er et eksempel på hvad et tidsstempel er :1079108400 <=> 16:20:00 03/12/04 (GMT)
og jeg bruger altså aller-senest tidsstempler fra januar af (hvilket giver flg. tidsstempel: 1079108400 - 60*60*24*31*3 = 1073751600, og altså ikke i nærheden af 0.)

Jeg ville kunne forstå det, hvis jeg skrev i nogle arrays, hvor jeg kunne risikere at skrive ud over enden, men det gør jeg jo bare ikke? Jeg læser rigtigt nok, men så længe jeg ikke skriver..

/Steffen
Avatar billede emmek Nybegynder
12. marts 2004 - 17:32 #4
Forresten.. Du kan ikke få et mini-setup, fordi der linkes til en MySql database og et mindre framework af kode (~100K linjer), men hvis du vil lægge din mail, eller skrive til steffen {at} schumacher {dot} dk så skal jeg nok sende dig koden, eller andre interesserede..

/Steffen
Avatar billede emmek Nybegynder
12. maj 2005 - 10:28 #5
Gnu har en slist som er en single-linked list.. Jeg arver fra denne og alt fungerer perfekt og næsten lige så effektivt.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester