[C++] Segmentatie errors na einde functie

Pagina: 1
Acties:

  • Netman768
  • Registratie: Augustus 2001
  • Laatst online: 08-12-2025
Goedendag allemaal

Voor mijn profielwerkstuk werk ik aan een programma dat tekstbestanden moet comprimeren. Dat werkt allemaal prima, maar ik loop tegen 1 gigantisch probleem aan. In mijn programma wordt nogal veel met grote strings tussen functies geschoven. Normaal werkt dit prima, maar af en toe krijg ik na het einde van de ene functie,. nog voor het begin van de andere functie (onderzocht d.m.v. cout-instructies) een segmentatie error. Nou weet ik dat een segmentatie-error hoort op te treden als je variablen door de war haalt, maar in dit geval is er niks met een variable whatsoever.

Ik heb een tijd gedacht dat de fout aan de return-instructie lag, maar ook een functie die geen waarde terug geeft (void functie(argumenten)) geeft een segmentatie error. Na veel gepuzzel ben ik er achter gekomen dat er stukjes compleet andere, allang uitgevoerde en correcte code zijn die het probleem veroorzaken. Er zit geen patroon of overeenkomst in die stukjes en het is compleet onvoorspelbaar of een stuk code een segmentation error zal veroorzaken voordat het gebeurt. Het verwijderen van die stukjes lost het probleem op, maar dat wil ik natuurlijk niet, ik weet ook lang niet altijd welk stukje het probleem vormt.

Het enige dat de stukjes in het gemeen hebben is dat ze data in de grote string aanpassen, verwijderen of toevoegen. Aangezien de hele functie daarom draait kan ik moeilijk dat er uit gaan slopen. Dan heb ik het nog niet eens er over dat ik in 80% van de gevallen niet weet welk stukje het probleem veroorzaakt.

Wat doe ik fout? Het ligt niet bij de return-queries, niet bij het echte aanpassen van de data (dan zou ik veel eerder een segmentation error moeten krijgen, niet pas na het beeindigen van de functie), het ligt niet bij de ontvangst van de data uit de functie (want ook als er geen data wordt teruggegeven gaat het fout). Het enige dat ik kan verzinnen is dat de inhoud van de string een probleem vormt, maar wat kan daar fout aan zijn? :?

Op google zoeken helpt me niet veel, de React-search maakt me niet wijzer, mijn boek biedt geen uitkomst. Ik zou eerlijk gezegd niet eens weten wat nou een goede beschrijvende zoek-query zou moeten zijn, 'C++ segmentatie fout' (of 'segmentation error') geeft niets terug dat hier op slaat... Ik hoop dat een van de die-hard coderts hier het probleem herkent :)

[edit] ik code onder linux (SuSe 8.2) met de G++ compiler uit GCC 3.2

Verwijderd

ik gok dat je ergens je stack verziekt waardoor ie na je return naar 'n fout adres terug springt daar random code begint uit te voeren wat uit eindelijk je segmentation fault tot gevolg heeft.

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
Een andere (gebruikelijkere) mogelijkheid is dat je heap naar de kloten is; in dat geval zal een dtor die een delete doet het probleem triggeren. De oorzaak is vaak eerder - heap errors worden vaak niet ontdekt op het moment dat ze ontstaan.

Wat voor string type gebruik je?

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • Buffy
  • Registratie: April 2002
  • Laatst online: 26-12-2024

Buffy

Fire bad, Tree pretty

Probeer het eens met valgrind, een memory debugger voor linux.
Heb het zelf nog niet gebruikt dus ben benieuwd of het wat is :)

[ Voor 9% gewijzigd door Buffy op 10-06-2003 12:02 . Reden: t -> d ]

That which doesn't kill us, makes us stranger - Trevor (AEon FLux)
When a finger points at the moon, the imbecile looks at the finger (Chinese Proverb)


Verwijderd

Klinkt inderdaad als memory corruption. Valgrind (ben ik erg over te spreken, maar ben nog niet overtuigd van z'n nut bij memory corruption, wel bij leaks e.d.) of electric fence zijn dan erg goede tools om mee te speurneuzen.

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 17-08 23:56

Janoz

Moderator Devschuur®

!litemod

Om de juiste posistie van je probleem te bepalen raad ik je aan om een echte debugger te gebruiken ipv cout (gd). Het komt vaak voor dat bepaalde output nog in de buffer zit (en niet op het scherm) waneer de segfault optreed (ookal heb je overal flushes bij gezet, ik spreek uit ervaring ;) ).

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


  • Netman768
  • Registratie: Augustus 2001
  • Laatst online: 08-12-2025
OK, ik heb valgrind gedownload, er wat mee rondgespeeld, maar ik kom er nog steeds niet goed uit. Ik krijg de volgende output:
Use of uninitialised value of size 4
at 0x4027AD6C: std::string::~string, char*) in (/pad/naar/file)
by 0x8049BD9: findandreplace(std::string, char*) in (/pad/naar/file)
by 0x80493F1: main (in /pad/naar/file)
by 0x403094C1: __libc_start_main (in /lib/i686/libc.so.6)

Invalid read size 4
at 0x4027AD6C: std::string::~string() (in /usr/lib/libstdc++.so.5.0.0)
by 0x8049BD9: findandreplace(std:string, char*) (in /pad/naar/file)
by 0x80493F1: main (in /pad/naar/file)
by 0x403094C1 __libc_start_main (in /lib/i686/libc.so.6)
Address 0xFFFFFFFC is not stack'd, malloc'd or free'd
Nou snap ik dat er dus iets mis is in de variable-huishouding, maar ik zou niet weten hoe ik het kan oplossen. Ik ben er inmiddels wel achter dat de fout wordt veroorzaakt door de volgende regel:
C++:
1
bestand = ereg_replace(ref_letter + stelsel(counter2),verw[counter2],bestand);
'refletter' bevat een constant karakter, voor het gemak ook een string. De regel roept 2 zelfgeschreven functies aan: stelsel, een manier om decimale getallen om te zetten in een 62-tallig getal en ereg_replace, een functie die ik heb vernoemd naar een PHP-functie en heel simpel een string door een andere string in een bepaalde string vervangt en dat uitpoept. Ik heb lopen testen, en als ik de stelsel-functie vervang door iets anders werkt het hele zooitje weer, de segmentation error wordt dus door de stelsel-functie veroorzaakt... Ik heb alleen geen flauw idee waarom... :X

De stelsel-functie ziet er zo uit:
C++:
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
string stelsel(int getal) {
    /* In deze functie zetten we een decimaal (10-tallig) cijfer om in een 62-tallig getal.
    Dat 62-tallige stelsel gebruikt 0-9, a-z en A-Z. Meer zou mogelijk zijn, maar is redelijk
    veel gedoe. */


    // declareer de 62-tallige karakters voor hun bijbehorende decimale getallen
    string verw2("0");
    chars[0] = "0"; chars[10] = "a"; chars[20] = "k"; chars[30] = "u"; chars[40] = "E"; chars[50] = "O"; chars[60] = "Y";
    chars[1] = "1"; chars[11] = "b"; chars[21] = "l"; chars[31] = "v"; chars[41] = "F"; chars[51] = "P"; chars[61] = "Z";
    chars[2] = "2"; chars[12] = "c"; chars[22] = "m"; chars[32] = "w"; chars[42] = "G"; chars[52] = "Q";
    chars[3] = "3"; chars[13] = "d"; chars[23] = "n"; chars[33] = "x"; chars[43] = "H"; chars[53] = "R";
    chars[4] = "4"; chars[14] = "e"; chars[24] = "o"; chars[34] = "y"; chars[44] = "I"; chars[54] = "S";
    chars[5] = "5"; chars[15] = "f"; chars[25] = "p"; chars[35] = "z"; chars[45] = "J"; chars[55] = "T";
    chars[6] = "6"; chars[16] = "g"; chars[26] = "q"; chars[36] = "A"; chars[46] = "K"; chars[56] = "U";
    chars[7] = "7"; chars[17] = "h"; chars[27] = "r"; chars[37] = "B"; chars[47] = "L"; chars[57] = "V";
    chars[8] = "8"; chars[18] = "i"; chars[28] = "s"; chars[38] = "C"; chars[48] = "M"; chars[58] = "W";
    chars[9] = "9"; chars[19] = "j"; chars[29] = "t"; chars[39] = "D"; chars[49] = "N"; chars[59] = "X";

    if (getal != 0) { // als het getal niet 0 is (zou berekening om zeep helpen)

        // kijk hoeveel karakters er maximaal nodig zijn voor 62-tallige weergave (in de praktijk is dit minder)
        int counter(0);
        for (counter = 0; getal > machten(62,counter); counter++) { }
        counter++;

        // declareer array voor de 62-tallige karakters en de decimale cijfers, van counter lang
        // (elk karakter z'n eigen array-entry), nodig voor het doortellen straks.
        string  letters[counter];
        int cijfers[counter];

        // zorg er voor dat de cijfers-array alles op 0 heeft staan
        for (int counter2 = 0; counter2 <= counter; counter2++) {
            cijfers[counter2] = 0;
        }

        // declareer variablen, current om te bepalen bij welke array-entry we bezig zijn
        int current(0), oudgetal(getal);

        /* Trek 1 van getal af, tot getal 0 is. Tel elke keer dat je wat af trekt van getal
        een op bij cijfers[0]. Als cijfers[0] 62 is, zet cijfers[0] op 0 en tel 1 bij
        cijfers[1] op. Als cijfers[1] 62 is, zet cijfers[1] op 0 en zet en tel 1 bij cijfers[3]
        op, enz. enz. */
        while (getal) {
            getal--;
            cijfers[0]++;

            for (current = 0; cijfers[current] > 61; current++) {
                cijfers[current + 1]++;
                cijfers[current] = 0;
            }

            for (current = 0; current < counter; current++) {
                letters[current] = chars[cijfers[current]];
            }
        }
        

        /* bepaal aan de hand van de cijfers-array hoeveel karakters er echt nodig waren voor
        het 62-tallige cijfer. Dit doen we door af te tellen en te kijken wanneer cijfers voor het
        eerste niet meer 0 is. De counter waar het ding dan op staat + 1 is de lengte van de
        verwijzing */
        while (!cijfers[counter]) {
            counter--;
        }
        counter++;

        // zet de letters in de goede volgorde in de string verw2
        verw2 = "";
        while (counter) {
            verw2 += letters[counter - 1];
            counter--;
        }
    }

    // geef verw2 terug aan findandrepalace
    return verw2;
}
Excuses voor de layout-verneuking.

Ik zie niet hoe dit later in het programma een segmentation error kan veroorzaken? Ik dacht eerst dat het probleem veroorzaakt zou worden doordat ik een functie aanroep met een andere functie als argument, maar ook als ik dat splits gaat het fout. 't spijt me dat ik jullie er weer mee lastig moet vallen, maar ik hoop dat jullie me hiermee kunnen helpen :)

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

Excuses voor de layout-verneuking.
Anders los je het ff op met een paar enters... :z

Professionele website nodig?


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-08 13:19

.oisyn

Moderator Devschuur®

Demotivational Speaker

En die char array initializatie kan ook wel mooier :)
C++:
1
2
3
4
5
6
7
8
for (int i = 0; i < 10; i++)
    chars[i] = '0' + i;

for (int i = 0; i < 26; i++)
{
    chars[i + 10] = i + 'a';
    chars[i + 10 + 26] = i + 'A';
}


En voordat iemand begint te ranten over dat ascii codes in principe niet portable zijn: zeur niet, wanneer komt dat nou voor :P

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Buffy
  • Registratie: April 2002
  • Laatst online: 26-12-2024

Buffy

Fire bad, Tree pretty

Op regel 29 en 30 defineer je arrays mbv de variable counter?

Vreemd, altijd gedacht dat het een constante expresie moest.

-edit-
Overigens wel een ingewikkelde functie. Doet dit niet het
zelfde:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int n = (int)(log(getal)/log(62)) + 1;

char* houder = new char[n];
int i = 0;

while (getal > 0 && i < n) {
    idx = getal % 62;
    houder[i++] = chars[idx];
    getal /= 62;
}
if (getal > 0) {
    cout << "oops";
}

string s;

while (i > 0) {
    s += houder[--i];
}

delete[] houder;

return s;

[ Voor 65% gewijzigd door Buffy op 10-06-2003 16:08 ]

That which doesn't kill us, makes us stranger - Trevor (AEon FLux)
When a finger points at the moon, the imbecile looks at the finger (Chinese Proverb)


Verwijderd

Je hebt counter2 als globale variabele en ook als teller gebruikt:

bestand = ereg_replace(ref_letter + stelsel(counter2),verw[(counter2],bestand);

for (int counter2 = 0; counter2 <= counter; counter2++) { cijfers[counter2] = 0; }

Dat zou ik sowieso even aanpassen :)

Verwijderd

Dawns_sister schreef op 10 juni 2003 @ 15:49:
Op regel 29 en 30 defineer je arrays mbv de variable counter?

Vreemd, altijd gedacht dat het een constante expresie moest.
Dat gold voor C, maar nooit voor C++ (en trouwens ook niet meer voor C99).

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-08 13:19

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op 10 juni 2003 @ 16:24:
[...]

Dat gold voor C, maar nooit voor C++ (en trouwens ook niet meer voor C99).
dat geldt dus wel voor C++. Dat het werkt is omdat het een gcc extensie is, maar een var kun je in C89/90 en C++ niet gebruiken om de lengte van een locale array mee te definieren

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • igmar
  • Registratie: April 2000
  • Laatst online: 29-06 18:56

igmar

ISO20022

Verwijderd schreef op 10 June 2003 @ 08:03:
Klinkt inderdaad als memory corruption. Valgrind (ben ik erg over te spreken, maar ben nog niet overtuigd van z'n nut bij memory corruption, wel bij leaks e.d.) of electric fence zijn dan erg goede tools om mee te speurneuzen.
Valgrind geeft ook de memory corruptie gewoon aan : Invalid writes, invalid reads.

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Verwijderd schreef op 10 June 2003 @ 16:24:
Dat gold voor C, maar nooit voor C++ (en trouwens ook niet meer voor C99).
VC6 geeft mij toch de foutmelding:
code:
1
error C2057: expected constant expression

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-08 13:19

.oisyn

Moderator Devschuur®

Demotivational Speaker

Dawns_sister schreef op 10 June 2003 @ 15:49:
Op regel 29 en 30 defineer je arrays mbv de variable counter?

Vreemd, altijd gedacht dat het een constante expresie moest.
zie mijn reactie hierboven, het is een gcc extensie :)
Overigens wel een ingewikkelde functie. Doet dit niet het
zelfde:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int n = (int)(log(getal)/log(62)) + 1;

char* houder = new char[n];
int i = 0;

while (getal > 0 && i < n) {
    idx = getal % 62;
    houder[i++] = chars[idx];
    getal /= 62;
}
if (getal > 0) {
    cout << "oops";
}

string s;

while (i > 0) {
    s += houder[--i];
}

delete[] houder;

return s;
Die log kun je ook wel achterwege laten, en dan gewoon doorgaat tot getal gelijk is aan 0 :) Een buffer van constante lengte gebruiken werkt hier ook wel, aangezien je weet dat een int maximaal INT_MAX is, en de string dus maximaal ceil (64log (INT_MAX)) = 6 chars is. Die ceil ben je overigens vergeten in je berekening (naar boven afronden is wel een vereiste)
Scheelt weer gebruik van de FPU en dus performance-winst :)

En als je dan toch een dynamische array wilt, gebruik dan std::vector<>, dat lost weer potentiele geheugenleaks op

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-08 13:19

.oisyn

Moderator Devschuur®

Demotivational Speaker

OlafvdSpek schreef op 10 June 2003 @ 16:30:
[...]

VC6 geeft mij toch de foutmelding:
code:
1
error C2057: expected constant expression
nou heeft VC6 hier toevallig gelijk, maar ik zou toch sterk aanraden om VC6 niet te gebruiken om te testen of iets volgens de standaard is ;)
ik gebruik zelf altijd de webversie van comeau. Altijd handig, zeker als je even geen compiler tot je beschikking hebt ;)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

.oisyn schreef op 10 June 2003 @ 16:29:
[...]


dat geldt dus wel voor C++.
Shit! Je hebt gelijk: "The C++ Programming Language", r.8.2.4 schrijft voor:
D1 [constant-expressionopt]

Wel mega suf dat dat er niet van het begin af aan inzit: je kon al wel "int* someArray = new int[foo]; ...; delete someArray;" doen, maar niet "int someArray[foo];"
Dat verdient (naar mijn mening) een |:( 7(8)7

[ Voor 16% gewijzigd door Verwijderd op 10-06-2003 16:50 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-08 13:19

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op 10 juni 2003 @ 16:47:
Wel mega suf dat dat er niet van het begin af aan inzit: je kon al wel "int* someArray = new int[foo]; ...; delete someArray;" doen, maar niet "int someArray[foo];"
Dat verdient (naar mijn mening) een |:( 7(8)7
Helemaal niet. De new werkt essentieel anders dan het definieren van een locale var. Bij new wordt namelijk een functie aangeroepen (de operator new ;)) met als parameter hoeveel bytes er gealloceerd moet worden. Dit is een runtime iets, en kan dus ook gewoon runtime veranderen.

Bij de allocatie van een array moet de stack aangepast worden. Als dit dynamisch moet gebeuren kan dat nogal wat problemen met zich meegeven, aangezien de variabelen die volgen op de array in het geheugen geen vast adres meer hebben. Het kan natuurlijk wel, maar er is wel iets voor te zeggen om het niet te implementeren.
Een andere quirk is dat sizeof () dan niet meer werkt, aangezien de lengte niet at runtime bekend is. En is het echte type van de array dan een int * ? (geen zin om de C99 reference erbij te pakken).
Ik weet nog dat in oude DOS omgevingen, zoals Turbo C, er een functie aalloc () was, dat stackgeheugen alloceerde door de stackpointer aan te passen. Wellicht dat het dan ook zo gaat

.edit: oh dat was alloca (), en die is er voor MSVC++ nog steeds :)
Lees ook hoe het niet aangeroepen kan worden in exception handlers: _alloca () in de MSDN library
Maareh, dan zou deze code alleen lopen op gcc beweer jij?
Ik beweer niets in die strekking, ik zeg enkel dat het in gcc werkt omdat het gcc een dergelijke extensie heeft. Misschien dat er nog andere compilers zijn met die extensie, maar daar laat ik me niet over uit

[ Voor 9% gewijzigd door .oisyn op 10-06-2003 17:00 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Buffy
  • Registratie: April 2002
  • Laatst online: 26-12-2024

Buffy

Fire bad, Tree pretty

.oisyn schreef op 10 June 2003 @ 16:34:
[...]
Die log kun je ook wel achterwege laten, en dan gewoon doorgaat tot getal gelijk is aan 0 :) Een buffer van constante lengte gebruiken werkt hier ook wel, aangezien je weet dat een int maximaal INT_MAX is, en de string dus maximaal ceil (64log (INT_MAX)) = 6 chars is. Die ceil ben je overigens vergeten in je berekening (naar boven afronden is wel een vereiste)
Scheelt weer gebruik van de FPU en dus performance-winst :)

En als je dan toch een dynamische array wilt, gebruik dan std::vector<>, dat lost weer potentiele geheugenleaks op
ceil is niet nodig omdat ik er standaard 1 bij de afgekapt waarde op tel.
Verder heb je helemaal gelijk met de constante buffer lengte al zet ik zo mijn vraagtekens bij het inwissellen van log operaties voor std::vector<> overhead.

Bedoeling van mijn voorbeeld was de TS te laten zien dat je ipv tel loops ook gewoon dingen kan berekenen.


Overigens is dit niet de oorzaak van de stack corruption:

C++:
1
2
3
4
5
6
7
string     letters[counter];
int    cijfers[counter];

// zorg er voor dat de cijfers-array alles op 0 heeft staan
for (int counter2 = 0; counter2 <= counter; counter2++) {
      cijfers[counter2] = 0;
} 

counter2 <= counter;

net over de rand lijkt me :)


edit:
Waarom werken de bold tags niet meer na een code blok?

[ Voor 5% gewijzigd door Buffy op 10-06-2003 17:12 ]

That which doesn't kill us, makes us stranger - Trevor (AEon FLux)
When a finger points at the moon, the imbecile looks at the finger (Chinese Proverb)


Verwijderd

.oisyn schreef op 10 June 2003 @ 16:56:
[...]


Helemaal niet. De new werkt essentieel anders dan het definieren van een locale var. Bij new wordt namelijk een functie aangeroepen (de operator new ;)) met als parameter hoeveel bytes er gealloceerd moet worden. Dit is een runtime iets, en kan dus ook gewoon runtime veranderen.
new => alloceren op de heap (@ runtime)
local array => alloceren op de stack (@runtime)

Dit kan op de heap, ik zie niet waarom dit niet zou kunnen op de stack... Niet met jouw argumenten in elk geval ;)

Een flinke onderschatting van Bjarne S., vind ik zelf. Niet meer dan logisch dat g++ dit wel doet.
Gemiste kans... (maar niemand is perfect, ook BS (blijkbaar ;) ) niet)
Ik beweer niets in die strekking, ik zeg enkel dat het in gcc werkt omdat het gcc een dergelijke extensie heeft. Misschien dat er nog andere compilers zijn met die extensie, maar daar laat ik me niet over uit
Ik drukte alleen mijn verwondering uit over het feit dat dit niet min of meer algemeen officieus wordt ondersteunt (waarbij ook ik niet geneigd ben VC mee te rekenen ;) )
Maar ja, als cumeau het zegt dan is het blijkbaar toch echt zo!!!

[ Voor 26% gewijzigd door Verwijderd op 10-06-2003 17:21 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-08 13:19

.oisyn

Moderator Devschuur®

Demotivational Speaker

Dawns_sister schreef op 10 June 2003 @ 17:10:
[...]


ceil is niet nodig omdat ik er standaard 1 bij de afgekapt waarde op tel.
Dan alloceer je potentieel 1 char teveel ;)
maar je hebt gelijk, ik zat even te denken aan een terminating \0, maar die heb je natuurlijk niet nodig :)
Verder heb je helemaal gelijk met de constante buffer lengte al zet ik zo mijn vraagtekens bij het inwissellen van log operaties voor std::vector<> overhead
std::vector<> heeft geen enkele overhead, hij doet gewoon een new (en initializeert 3 pointers, maar dat mag geen naam hebben). Ook de [] operator heeft geen overhead
Voordeel van std::vector is dat hij automatish opgeruimd wordt als ie buiten scope gaat. Jij hebt met jouw code een memory leak als er ergens een exception optreedt

[ Voor 11% gewijzigd door .oisyn op 10-06-2003 17:15 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Verwijderd schreef op 10 juni 2003 @ 17:12:
Dit kan op de heap, ik zie niet waarom dit niet zou kunnen op de stack... Niet met jouw argumenten in elk geval ;)
Omdat zoals .oisyn al aangaf je dan een stackframe nodig hebt met een dynamic layout, terwijl de meeste compilers een stackframe met een static layout gebruiken.

Hoe is het in gcc eigenlijk geimplementeerd? Echt op de stack of intern toch met new/delete?

[ Voor 12% gewijzigd door Olaf van der Spek op 10-06-2003 17:23 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-08 13:19

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op 10 juni 2003 @ 17:12:
Dit kan op de heap, ik zie niet waarom dit niet zou kunnen op de stack... Niet met jouw argumenten in elk geval ;)

Een flinke onderschatting van Bjarne S., vind ik zelf. Niet meer dan logisch dat g++ dit wel doet.
Gemiste kans... (maar niemand is perfect, ook BS (blijkbaar ;) ) niet)
Ik vind het nogal inintuitief als je een int bla[localeVar] declareert, dat bla eigenlijk een int *& is, en geen int (&)[x]

Bovendien werken exception handlers niet in een stackframe, zoals je op de MSDN pagina kunt lezen. Het dynamisch alloceren van geheugen op de stack kan dan ook niet (en ik denk dat dit de voornaamste reden is dat het niet in C++ zit, maar wel in C99). 'Vaste' locale variabelen kunnen natuurlijk wel, die kunnen gewoon in de stackframe van de enclosing function worden gealloceerd

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

OlafvdSpek schreef op 10 June 2003 @ 17:22:
[...]

Omdat zoals .oisyn al aangaf je dan een stackframe nodig hebt met een dynamic layout, terwijl de meeste compilers een stackframe met een static layout gebruiken.

Hoe is het in gcc eigenlijk geimplementeerd? Echt op de stack of intern toch met new/delete?
Stack. Maar op heap zou ook een optie zijn geweest.

Maar idd, de compilers toen zullen dit wellicht niet aangekund hebben...

[ Voor 3% gewijzigd door Verwijderd op 10-06-2003 17:29 ]


  • Netman768
  • Registratie: Augustus 2001
  • Laatst online: 08-12-2025
Goed, allereerst iedereen bedankt voor de verbeteringen voor de code. Ik ben nog maar een jong, groen prutsertje dus alle suggesties zijn welkom :P

Ik heb ook het probleem gevonden. Het heeft te maken met deze regel:
C++:
1
bestand = ereg_replace(ref_letter + stelsel(counter2),verw[counter2],bestand);
Wanneer ref_letter "^" is (wat het was), loopt het hele zooitje aan het einde van de functie vast. De reden is mij geheel onduidelijk.

* Netman768 gaat op zen gemakkie het topic eens nauwkeurig doorlezen om de gesuggereerde verbeteringen aan te brengen.

Tnx mensen :)

  • Buffy
  • Registratie: April 2002
  • Laatst online: 26-12-2024

Buffy

Fire bad, Tree pretty

.oisyn schreef op 10 June 2003 @ 17:14:
[...]


Dan alloceer je potentieel 1 char teveel ;)
maar je hebt gelijk, ik zat even te denken aan een terminating \0, maar die heb je natuurlijk niet nodig :)
Nee hoor, voorbeeldjes:

10-talig62-taligint(log(n)/log(62)) + 1
62102
3843ZZ2
38441003


[...]
std::vector<> heeft geen enkele overhead, hij doet gewoon een new (en initializeert 3 pointers, maar dat mag geen naam hebben). Ook de [] operator heeft geen overhead
Maar std::vector<> doet toch voor elke push_back een new, tenzij je van te voren reserve() aanroept met te verwachten aantal cijfers (wink-wink, log-log, nudge-nudge)
Voordeel van std::vector is dat hij automatish opgeruimd wordt als ie buiten scope gaat. Jij hebt met jouw code een memory leak als er ergens een exception optreedt

Bang zijn voor een exception uit een standaard C loop met alleen int en char variabelen.
En dat voor iemand die dit durft te zeggen >:)

[quote].oisyn schreef op 10 June 2003 @ 15:40:
[..]
En voordat iemand begint te ranten over dat ascii codes in principe niet portable zijn: zeur niet, wanneer komt dat nou voor :P[/quote]
Nevermind, cout en string kunnen natuurlijk wel met exceptions smijten. zei iemand auto_ptr<> :)

[ Voor 8% gewijzigd door Buffy op 10-06-2003 17:55 ]

That which doesn't kill us, makes us stranger - Trevor (AEon FLux)
When a finger points at the moon, the imbecile looks at the finger (Chinese Proverb)


  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Verwijderd schreef op 10 juni 2003 @ 17:28:
Stack. Maar op heap zou ook een optie zijn geweest.

Maar idd, de compilers toen zullen dit wellicht niet aangekund hebben...
Maar dan krijg je weer van die vreemde uitzonderingen zoals: Een array komt op de stack als size beschikbaar is tijdens compilen en anders op de heap.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-08 13:19

.oisyn

Moderator Devschuur®

Demotivational Speaker

Dawns_sister schreef op 10 juni 2003 @ 17:47:
[...]


Nee hoor, voorbeeldjes:

10-talig62-taligint(log(n)/log(62)) + 1
62102
3843ZZ2
38441003
right again, als 62log n een geheel getal is, zoals bijvoorbeeld bij n=62, moet er natuurlijk 1 cijfer meer geoutput worden
Maar std::vector<> doet toch voor elke push_back een new, tenzij je van te voren reserve() aanroept met te verwachten aantal cijfers (wink-wink, log-log, nudge-nudge)
ik had het over het gebruik van een std::vector ipv een new. Uiteraard is het gebruik het efficientst als je het van tevoren alloceert, maar dat deed je bij new ook al. Het voordeel van een std::vector tov een new is dus de extra safety, dat was mijn hele punt
zei iemand auto_ptr<> :)
auto_ptr doet een delete, geen delete[], en kun je dus niet gebruiken voor arrays
De reden dat er geen std::auto_array is is omdat er een std::vector bestaat die precies hetzelfde kan :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Netman867 schreef op 10 juni 2003 @ 17:38:
Goed, allereerst iedereen bedankt voor de verbeteringen voor de code. Ik ben nog maar een jong, groen prutsertje dus alle suggesties zijn welkom :P

Ik heb ook het probleem gevonden. Het heeft te maken met deze regel:
C++:
1
bestand = ereg_replace(ref_letter + stelsel(counter2),verw[counter2],bestand);
Wanneer ref_letter "^" is (wat het was), loopt het hele zooitje aan het einde van de functie vast. De reden is mij geheel onduidelijk.

* Olaf van der Spek gaat op zen gemakkie het topic eens nauwkeurig doorlezen om de gesuggereerde verbeteringen aan te brengen.

Tnx mensen :)
^ heeft waarschijnlijk een speciale betekenis en moet geescaped worden.

  • Buffy
  • Registratie: April 2002
  • Laatst online: 26-12-2024

Buffy

Fire bad, Tree pretty

.oisyn schreef op 10 June 2003 @ 18:07:
[...]

auto_ptr doet een delete, geen delete[], en kun je dus niet gebruiken voor arrays
De reden dat er geen std::auto_array is is omdat er een std::vector bestaat die precies hetzelfde kan :)
aargg 8)7

Er zijn ook zoveel valkuilen, soms is het meer een hindernisbaan lopen dan programeren :)


Overigens moet TS toch nog eens naar die for-loop op regel 33 kijken. volgens mij zit daar de heap corruption.

That which doesn't kill us, makes us stranger - Trevor (AEon FLux)
When a finger points at the moon, the imbecile looks at the finger (Chinese Proverb)


Verwijderd

OlafvdSpek schreef op 10 June 2003 @ 18:07:
[...]

Maar dan krijg je weer van die vreemde uitzonderingen zoals: Een array komt op de stack als size beschikbaar is tijdens compilen en anders op de heap.
Vreemde uitzonderingen :? Daar heb je een compiler voor... ;)

Misschien heeft het iets te maken met iets als een "DSP-C++ standaard" :? , een term die ik wel eens in een manual heb opgemerkt (maar waar ik 1..2..3 niets over kan vinden), maar twee (aanzienlijk) verschillende DSP compilers waar ik nu bij kan, ondersteunen wel een dynamische locale array op de stack. Dit gebeurt wel met behulp van een (pseudo) frame-pointer, net als gcc dit lijkt te doen... Een derde (microcontroller) compiler ondersteunt het met behulp van de heap en meer kan ik nu even niet testen :D

Alle drie van andere compilerbouwers.

En gcc doet het ook helemaal op de stack, ook met behulp van een framepointer.

Maar ze lijken het tot nu toe allemaal te kunnen, dacht daarom altijd dat het officieel C++ was...
Dawns_sister schreef op 10 juni 2003 @ 17:47:
Maar std::vector<> doet toch voor elke push_back een new, tenzij je van te voren reserve() aanroept met te verwachten aantal cijfers (wink-wink, log-log, nudge-nudge)
Dat is uiteraard implementatieafhankelijk, maar de meeste implementaties alloceren/reserveren per chunks van bijvoorbeeld 2k (net zoals malloc in C dat ook doet bij de meeste implementaties).

[ Voor 19% gewijzigd door Verwijderd op 10-06-2003 20:05 ]


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
Dawns_sister schreef op 10 June 2003 @ 17:47:
Maar std::vector<> doet toch voor elke push_back een new, tenzij je van te voren reserve() aanroept met te verwachten aantal cijfers (wink-wink, log-log, nudge-nudge)
Nee. push_back() is gemiddeld O(1). Dat is alleen haalbaar door expontentiele groei, dwz Groei met factor N als je geheugen vol is.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Verwijderd schreef op 10 June 2003 @ 19:50:
Vreemde uitzonderingen :? Daar heb je een compiler voor... ;)
Het heeft wel gevolgen voor bijvoorbeeld performance.
En wat bijvoorbeeld als de heap corrupt/vol is? Dan ga jij (of de compiler voor jou) in de error-handling routine vrolijk een array op de heap alloceren?
Pagina: 1