[C++] a[0] = b ===> Segmentation Fault

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Comp_Lex
  • Registratie: Juni 2005
  • Laatst online: 23:50
Hallo,

ik heb een (voor mij) vreemd probleem waar ik momenteel even niet uitkom. Het is een probleem waarvan je de oplossing niet makkelijk met Google vindt of je vindt wel wat maar dan worden de problemen veroorzaakt door andere zaken die niets met je eigen implementatie te maken hebben. (Of juist wel, maar ik ben dan ook een noob, ik snap er niks van en ik zie het even niet meer)

Programma: Sokath - http://sokath.sourceforge.net/

Too Long; Didn't Read: Programma draaide in het verleden altijd goed en stabiel. Ik verhoog lengte van array met 1, voeg extra info toe, dan crasht het programma op een gegeven moment (dus niet direct) en ik heb niks aan de implementatie van functies veranderd.

Deel van de code:

Header
C++:
1
HubbertCurve hcs[23];


Implementatie met context
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
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
105
106
void Analyzer::calculateHubbertCurve(string regionName) {

    int cumProdTemp;
    vector<double> oneDivP;
    deque<double> timelinePart1;
    deque<double> timelinePart2;

    for (int i = 0; i < (int)regions.size(); i++) { //global regionPos!
        if (regions[i].getName() == regionName) {
            regionPos = i;
        }
    }

    firstYear = regions.at(regionPos).getFirstYear();
    lastYear = regions.at(regionPos).getLastYear();

    readData(regionName);

    regions.at(regionPos).setFirstYear(firstYear);
    regions.at(regionPos).setLastYear(lastYear);

    double temp = cumProd / 0.365;

    for (int i = readProd.size() - 1; i >= 0; i--) {
        cumProds.push_front(temp);
        temp -= (readProd.at(i));
    }

    begin = -1;
    end = -1;

    for (int i = 0; i < (int)readTimeline.size(); i++) {
        if (firstYear == readTimeline.at(i)) {
            begin = i;
        }
        if (lastYear == readTimeline.at(i)) {
            end = i;
        }
    }

    if ((begin == -1) || (end == -1)) {
        wxMessageBox(wxT("First datapoint and/or last datapoint choices are illegal. Hubbert Linearization computation will now fail."), wxT("Error"), wxOK | wxICON_ERROR);
        calculationFinished = true;
    }
    else if (((end - begin) < 3) && ((end - begin) > 0)) {
        wxMessageBox(wxT("It is not recommended to do Hubbert Linearization with 2 datapoints. Hubbert Linearization gives worse results with less datapoints."), wxT("Error"), wxOK | wxICON_ERROR);
    }
    else {

        for (int i = 0; i < (int)readProd.size(); i++) {
            pDivQ.push_back((readProd.at(i)) / (cumProds.at(i)));
        }

        hls[regionPos] = getHubbertLine();

        int maxQ = (int)qt;

        for (int i = 1; i <= maxQ; i++) {
            anProds.push_back((start * i * (1 - (((float)i) / qt))));
            oneDivP.push_back(1 / anProds.back());
        }

        cumProdTemp = (int)cumProds.at(end) - 1;

        for (int i = 0; i < (int)cumProds.size(); i++) {
            Q.push_back(cumProds.at(i) * 0.365);
        }

        if (cumProdTemp >= maxQ) {
            wxString region(regionName.c_str(), wxConvUTF8);
            wxMessageBox(wxT("Error with region: ") + region + wxT("\nCumulative production greater than Ultimate Recoverable Resources.\nPlease set the datapoints for Hubbert Linearization manually."), wxT("Error"), wxOK | wxICON_ERROR);
            vector <double> nothing1;
            vector <double> nothing2;
            HubbertCurve hc(nothing1, nothing2);
            HubbertLine hl(0.0f, 0.0f, 0.0f);
            hcs[regionPos] = hc;
            hls[regionPos] = hl;
            regions.at(regionPos).setPDivQ(pDivQ);
            regions.at(regionPos).setQ(Q);
        }
        else {
            timelinePart1.push_front(readTimeline.at(end));
            for (int i = cumProdTemp - 1; i > 0; i--) {
                timelinePart1.push_front(timelinePart1.front() - oneDivP.at(i + 1));
            }
            timelinePart2.push_back(readTimeline.at(end) + oneDivP.at(cumProdTemp));
            for (int i = cumProdTemp + 1; i < maxQ; i++) {
                timelinePart2.push_back(timelinePart2.back() + oneDivP.at(i));
            }
            for (int i = 0; i < (int)timelinePart1.size(); i++) {
                timeline.push_back(timelinePart1.at(i));
            }

            for (int i = 0; i < (int)timelinePart2.size(); i++) {
                timeline.push_back(timelinePart2.at(i));
            }

            regions.at(regionPos).setPDivQ(pDivQ);
            regions.at(regionPos).setQ(Q);
            HubbertCurve hc(anProds, timeline);
            printf("%s %i %i %i %f %f\n", regionName.c_str(), regionPos, (int)hc.getProduction().size(), (int)hc.getTimeline().size(), hc.getPeakYear(), hc.getPeakProduction());
            hcs[regionPos] = hc; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Segmentation Fault als regionPos == 0

        }
    }
}


Het probleem bevindt zich op regel 102. Als "regionPos" gelijk is aan 0 dan segfault het programma. De functie zelf wordt trouwens meerdere keren aangeroepen. De variabele "regionPos" is in eerste instantie ook niet gelijk aan 0. Het is bijvoorbeeld eerst gelijk aan 22. De kopieren van de data gaat dan goed en later gaat het dus fout. (Voorbeeld "regionPos" sequentie: 22, 0, 4, 7, 5, 12......)
Als ik de lengte van het array met 1 kleiner maak (dus size == 22) en wat gegevens weglaat, dan draait het programma hartstikke goed zonder problemen (of ik heb constant ontzettend veel geluk gehad met mijn (misschien zwaar baggere) implementatie). Wat ik eigenlijk gedaan heb is de lengte van het array ophogen met 1 en wat extra informatie toegevoegd => Segmentation Fault als er aan bepaalde condities worden voldaan.

Dit is het debug informatie:

#0 0xb6fcb463 memmove() (/lib/tls/i686/cmov/libc.so.6:??)
#1 0x80629b7 std::__copy<true, std::random_access_iterator_tag>::copy<double>(__first=0x8795ce0, __last=0x87971f0, __result=0x1) (/usr/include/c++/4.2/bits/stl_algobase.h:298)
#2 0x80629f6 std::__copy_aux<double const*, double*>(__first=0x8795ce0, __last=0x87971f0, __result=0x1) (/usr/include/c++/4.2/bits/stl_algobase.h:315)
#3 0x8062b92 std::__copy_normal<true, true>::__copy_n<__gnu_cxx::__normal_iterator<double const*, std::vector<double, std::allocator<double> > >, __gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > > >(__first={_M_current = 0x8795ce0}, __last={_M_current = 0x87971f0}, __result={_M_current = 0x1}) (/usr/include/c++/4.2/bits/stl_algobase.h:368)
#4 0x8062be4 std::copy<__gnu_cxx::__normal_iterator<double const*, std::vector<double, std::allocator<double> > >, __gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > > >(__first={_M_current = 0x8795ce0}, __last={_M_current = 0x87971f0}, __result={_M_current = 0x1}) (/usr/include/c++/4.2/bits/stl_algobase.h:401)
#5 0x8062eb0 std::vector<double, std::allocator<double> >::operator=(this=0x8471828, __x=@0xbfbe4ae8) (/usr/include/c++/4.2/bits/vector.tcc:151)
#6 0x807513b HubbertCurve::operator=(this=0x8471828) (/home/alexander/SourceForge/sokath/source/Sokath/HubbertCurve.h:17)
#7 0x806f782 Analyzer::calculateHubbertCurve(this=0x8471748, regionName=@0xbfbe4d20) (/home/alexander/SourceForge/sokath/source/Sokath/Analyzer.cpp:140)

Valgrind info:

==6433==
==6433== Invalid write of size 1
==6433== at 0x4023DBC: memmove (mc_replace_strmem.c:516)
==6433== by 0x80629B6: double* std::__copy<true, std::random_access_iterator_tag>::copy<double>(double const*, double const*, double*) (stl_algobase.h:298)
==6433== by 0x80629F5: double* std::__copy_aux<double const*, double*>(double const*, double const*, double*) (stl_algobase.h:315)
==6433== by 0x8062B91: __gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > > std::__copy_normal<true, true>::__copy_n<__gnu_cxx::__normal_iterator<double const*, std::vector<double, std::allocator<double> > >, __gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > > >(__gnu_cxx::__normal_iterator<double const*, std::vector<double, std::allocator<double> > >, __gnu_cxx::__normal_iterator<double const*, std::vector<double, std::allocator<double> > >, __gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > >) (stl_algobase.h:368)
==6433== by 0x8062BE3: __gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > > std::copy<__gnu_cxx::__normal_iterator<double const*, std::vector<double, std::allocator<double> > >, __gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > > >(__gnu_cxx::__normal_iterator<double const*, std::vector<double, std::allocator<double> > >, __gnu_cxx::__normal_iterator<double const*, std::vector<double, std::allocator<double> > >, __gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > >) (stl_algobase.h:401)
==6433== by 0x8062EAF: std::vector<double, std::allocator<double> >::operator=(std::vector<double, std::allocator<double> > const&) (vector.tcc:151)
==6433== by 0x807513A: HubbertCurve::operator=(HubbertCurve const&) (HubbertCurve.h:17)
==6433== by 0x806F781: Analyzer::calculateHubbertCurve(std::string) (Analyzer.cpp:140)

###########################

Je ziet dat (de default) "operator=" van HubbertCurve wordt aangeroepen, waarbij de "operator=" van vectoren worden aangeroepen.

Hier is de code van de Hubbert Curve datastructuur:

Header
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
/***************************************************************
 * Name:      HubbertCurve.h
 * Purpose:   Defines Hubbert Curve
 * Author:    Alexander Jurjens (ajurjens@gmail.com)
 * Created:   2007-06-22
 * Copyright: Alexander Jurjens (http://www.sourceforge.net/projects/sokath)
 * License:   GNU GPLv2 or (optionally) later
 **************************************************************/

#ifndef HUBBERTCURVE_H_INCLUDED
#define HUBBERTCURVE_H_INCLUDED

#include <vector>

using namespace std;

class HubbertCurve {

    public:
        HubbertCurve() {};
        HubbertCurve(vector<double> anProd, vector<double> timeline);
        ~HubbertCurve();
        void setProduction(vector<double> anProd);
        void setTimeline(vector<double> _timeline) { timeline = _timeline; }
        vector<double> getProduction() { return annualProduction; }
        vector<double> getTimeline() { return timeline; }
        double getPeakProduction() { return peakProduction; }
        double getPeakYear() { return peakYear; }
        void setMultiProd(vector<double> anProd);
        vector<double> getMultiProd() { return multiAnnualProduction; }
        void setMultiTimeline(vector<double> timeline) { multiTimeline = timeline; }
        vector<double> getMultiTimeline() { return multiTimeline; }

    private:
        vector<double> annualProduction; // annual Production
        vector<double> timeline; // timeline
        double peakProduction;
        double peakYear;
        vector<double> multiAnnualProduction; // Multi-Cycle Hubbert Curves
        vector<double> multiTimeline;
};

#endif // HUBBERTCURVE_H_INCLUDED


Implementatie
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
/***************************************************************
 * Name:      HubbertCurve.cpp
 * Purpose:   Code for Hubbert Curve
 * Author:    Alexander Jurjens (ajurjens@gmail.com)
 * Created:   2007-06-22
 * Copyright: Alexander Jurjens (http://www.sourceforge.net/projects/sokath)
 * License:   GNU GPLv2 or (optionally) later
 **************************************************************/

#include "HubbertCurve.h"

#include <iostream>

using namespace std;

HubbertCurve::HubbertCurve(vector<double> anProd, vector<double> _timeline) {

    annualProduction = anProd;
    timeline = _timeline;

    peakProduction = 0;
    peakYear = 0;
    int peak = 0;
    if (anProd.size() > 0) {
        for (int i = 0; i < (int)anProd.size(); i++) {
            if (peakProduction < anProd.at(i)) {
                peakProduction = anProd.at(i);
                peak = i;
            }
        }
        peakYear = timeline.at(peak);
    }
}

HubbertCurve::~HubbertCurve() {
}

void HubbertCurve::setProduction(vector<double> anProd) {

    annualProduction = anProd;
    int peak = 0;

    for (int i = 0; i < (int) annualProduction.size(); i++) {
        if (peakProduction < annualProduction.at(i)) {
            peakProduction = annualProduction.at(i);
            peak = i;
        }
    }
}

void HubbertCurve::setMultiProd(vector<double> anProd) {

    multiAnnualProduction = anProd;
    int peak = 0;
    peakProduction = 0.0;

    for (int i = 0; i < (int) multiAnnualProduction.size(); i++) {
        if (peakProduction < multiAnnualProduction.at(i)) {
            peakProduction = multiAnnualProduction.at(i);
            peak = i;
        }
    }
    //printf("%i %i\n", (int)multiTimeline.size(), peak);
    peakYear = multiTimeline.at(peak);
}


Tijdens het construeren van de HubbertCurve blijven bepaalde vectoren gewoon leeg. In het debug info zie je dat er een "operator=" van een vector wordt aangeroepen dat niet helemaal goed wordt uitgevoerd. Zou het kopieren van lege vectoren naar andere lege vectoren/lege plekken in het geheugen misschien te maken hebben met de segmentation fault? Ik weet het zelf niet, maar misschien weten jullie het. Als je vectoren trouwens zo declareert in een header, heeft het al ook een default grootte? Bevat het dan ook default waarden of moet je zoiets doen als (Java) "new Vector()" om een NullPointerException te voorkomen?
Wat met trouwens niet lekker zit is dingen als "__result={_M_current = 0x1}" in het debug info. Ik denk dat het te maken heeft met null pointers of iets dergelijks, maar ik weet verder eigenlijk niet wat het betekent en als je dan gaat Googlen dan vind je niks (of ik Google verkeerd, dat kan natuurlijk ook). Ik hoop dat jullie meer weten wat mijn probleem nou eigenlijk is en wat bepaalde dingen betekenen.

PS. Ik ga nu even weg. Als jullie meer info nodig hebben, zeg het dan even en dan voeg ik het later toe :)

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 00:27

.oisyn

Moderator Devschuur®

Demotivational Speaker

De fout zit niet daar, maar elders. Het feit dat ie op die regel crasht is daar slechts een symptoom van, omdat iets anders de state compleet vernaggelt. Weet je zeker dat regionPos nooit groter wordt dan 22? Ook kan de fout op een compleet andere plek in de applicatie zitten. Al zie ik wel dat je valgrind gebruikt, die zou dat op zich moeten kunnen detecteren.

[ Voor 27% gewijzigd door .oisyn op 09-07-2010 15:40 ]

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.


Acties:
  • 0 Henk 'm!

  • 4VAlien
  • Registratie: November 2000
  • Laatst online: 24-06 09:47

4VAlien

Intarweb!

druk je de extra info ook af in het printf statement? stack corruptie met foutief printf gebruik is namelijk niet zo heel moeilijk te bereiken :)

Acties:
  • 0 Henk 'm!

  • Comp_Lex
  • Registratie: Juni 2005
  • Laatst online: 23:50
Dit is het output van het programma op de console:

World 22 6845 6845 2009,966553 79,677606
Africa 0 674 674 2013,521601 9,785594
Segmentatiefout

Het getal na de "regionName" is "regionPos".

Maar goed wat ik al zei, ik ben een noob, dus ik ben ook een noob met valgrind :)
Maar ik ben al bezig met het bekijken van tutorials.

EDIT:

Nog een beetje extra info van valgrind:

==6637== Address 0x1 is not stack'd, malloc'd or (recently) free'd
==6637==
==6637== Process terminating with default action of signal 11 (SIGSEGV)
==6637== Access not within mapped region at address 0x1
==6637== at 0x4023DBC: memmove (mc_replace_strmem.c:516)
==6637== by 0x80629B6: double* std::__copy<true, std::random_access_iterator_tag>::copy<double>(double const*, double const*, double*) (stl_algobase.h:298)
==6637== by 0x80629F5: double* std::__copy_aux<double const*, double*>(double const*, double const*, double*) (stl_algobase.h:315)
==6637== by 0x8062B91: __gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > > std::__copy_normal<true, true>::__copy_n<__gnu_cxx::__normal_iterator<double const*, std::vector<double, std::allocator<double> > >, __gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > > >(__gnu_cxx::__normal_iterator<double const*, std::vector<double, std::allocator<double> > >, __gnu_cxx::__normal_iterator<double const*, std::vector<double, std::allocator<double> > >, __gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > >) (stl_algobase.h:368)
==6637== by 0x8062BE3: __gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > > std::copy<__gnu_cxx::__normal_iterator<double const*, std::vector<double, std::allocator<double> > >, __gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > > >(__gnu_cxx::__normal_iterator<double const*, std::vector<double, std::allocator<double> > >, __gnu_cxx::__normal_iterator<double const*, std::vector<double, std::allocator<double> > >, __gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > >) (stl_algobase.h:401)
==6637== by 0x8062EAF: std::vector<double, std::allocator<double> >::operator=(std::vector<double, std::allocator<double> > const&) (vector.tcc:151)
==6637== by 0x807513A: HubbertCurve::operator=(HubbertCurve const&) (HubbertCurve.h:17)
==6637== by 0x806F781: Analyzer::calculateHubbertCurve(std::string) (Analyzer.cpp:140)
==6637== by 0x8077C3D: Controller::calculateHubbertCurve(std::string) (Controller.cpp:13)
==6637== by 0x808B1EF: HubbertCurvePanel::update() (HubbertCurvePanel.cpp:439)
==6637== by 0x8090F89: HubbertCurvePanel::HubbertCurvePanel(wxWindow*, Controller*) (HubbertCurvePanel.cpp:192)
==6637== by 0x80CB51C: WxNotebookPanel::WxNotebookPanel(wxWindow*) (WxNotebookPanel.cpp:22)
==6637==

Ik kijk nog even verder.

[ Voor 104% gewijzigd door Comp_Lex op 09-07-2010 20:14 ]


Acties:
  • 0 Henk 'm!

  • user109731
  • Registratie: Maart 2004
  • Niet online
Je compileert wel met -Wall en gebruikt een debug build (-O0 -g)?

Valgrind memcheck is redelijk straight-forward:
code:
1
valgrind --tool=memcheck ./app bla


Is hls even groot als hcs? Je weet dat in een array gedefinieerd als "Foo hls[22]" index 22 ongeldig is? Voor de rest zie ik in deze code niet direct iets wat zeker weten de oorzaak is...

edit: let wel op dat anProds.back() niet gedefinieerd is als anProds leeg is. Is dat niet het geval?

[ Voor 14% gewijzigd door user109731 op 09-07-2010 20:43 ]


Acties:
  • 0 Henk 'm!

  • Comp_Lex
  • Registratie: Juni 2005
  • Laatst online: 23:50
Ja hls is even groot als hcs. Daar worden HubbertLines in opgeslagen. Het vreemde is wel dat ik daar geen problemen mee heb. Ik kan met Valgrind nog niet goed het probleem tracen. Het wijst ook naar die ene regel en traced het dan door naar memmove() via operator= van vector. Er gebeurt waarschijnlijk op een andere plek iets geks, maar het rare is dat ik tot nu toe alleen triviale wijzigingen heb doorgevoerd (zoals array size met 1 ophogen). Ik zal even weer kijken of alles verder wel klopt.

Acties:
  • 0 Henk 'm!

  • user109731
  • Registratie: Maart 2004
  • Niet online
Om deze vraag nog te beantwoorden:
Comp_Lex schreef op vrijdag 09 juli 2010 @ 15:29:
Wat met trouwens niet lekker zit is dingen als "__result={_M_current = 0x1}" in het debug info. Ik denk dat het te maken heeft met null pointers of iets dergelijks, maar ik weet verder eigenlijk niet wat het betekent en als je dan gaat Googlen dan vind je niks (of ik Google verkeerd, dat kan natuurlijk ook). Ik hoop dat jullie meer weten wat mijn probleem nou eigenlijk is en wat bepaalde dingen betekenen.
vector::operator= doet o.a. het volgende om alle data te kopieren:
C++:
1
2
std::copy(__x._M_impl._M_start, __x._M_impl._M_start + size(),
            this->_M_impl._M_start);

Vervolgens zie je in de callstack dat std::copy word aangeroepen met het laatste argument 0x1. Vervolgens doetie daar een memmove naar, en dat gaat verkeerd (0x1 is een near-null pointer). Ergens wordt _M_start overschreven, waarschijnlijk door een buffer overrun ofzo.

Je zegt dat het fout gaat met index 0, dus hcs[0] wordt overschreven. Kijk eens heel goed naar alle andere members van Analyzer, en in het bijzonder die vlak voor hcs. Bij het toewijzen daarvan gaat iets fout denk ik.

[ Voor 11% gewijzigd door user109731 op 09-07-2010 21:24 ]


Acties:
  • 0 Henk 'm!

  • Comp_Lex
  • Registratie: Juni 2005
  • Laatst online: 23:50
JanDM schreef op vrijdag 09 juli 2010 @ 21:16:
Je zegt dat het fout gaat met index 0, dus hcs\[0] wordt overschreven. Kijk eens heel goed naar alle andere members van Analyzer, en in het bijzonder die vlak voor hcs. Bij het toewijzen daarvan gaat iets fout denk ik.
Dank u wel! _/-\o_ _/-\o_ _/-\o_

Met deze informatie heb ik de bug inderdaad opgelost! Er werd even iets teveel gedaan met een simpel boolean arraytje wat daarvoor kwam :)
Weer wat geleerd :)

EDIT: wel vreemd trouwens dat 'ie niet segfaulte met het boolean array, is dat normaal met C++?

[ Voor 8% gewijzigd door Comp_Lex op 09-07-2010 21:44 ]


Acties:
  • 0 Henk 'm!

  • user109731
  • Registratie: Maart 2004
  • Niet online
Mooi zo, 0x1 kan idd goed boolean true zijn :)
Comp_Lex schreef op vrijdag 09 juli 2010 @ 21:42:
EDIT: wel vreemd trouwens dat 'ie niet segfaulte met het boolean array, is dat normaal met C++?
Een segfault is op een lager niveau, dat gaat over memory pages. Het OS kijkt enkel of het proces toegang heeft tot een page, wat het proces daar vervolgens mee doet maakt 'm niets uit. C++ doet ook geen bounds-checking op je array.
C++:
1
2
bool* arr = new bool[10];
arr[13] = true;

arr staat op de heap, en je weet niet wat erachter staat. Is dat adres niet beschikbaar dan zal het OS een segfault signal sturen (hoeft dus niet altijd te gebeuren!), je mag immers niet naar geheugen schrijven dat niet netjes via het OS gealloceerd is. In jouw geval is een Analyzer object echter 1 blok geheugen achter elkaar, zoiets:
C++:
1
2
bool arr[10];
int foo[23];

De ints komen nu (in het geheugen) achter de booleans. arr[13] zal niet segfaulten, er is immers nog een geldig stuk geheugen erachter beschikbaar. Dat daar ints staan en geen booleans weet het OS niet eens.

De segfault in de TS kwam omdat naar 0x01 geschreven werd, alle (moderne?) OS'en zorgen ervoor dat 0x0 nooit wordt toegewezen en direct crasht. Anders zou je een null-pointer kunnen dereferencen zonder crashes, omdat het adres toevallig geldig kan zijn.

Valgrind memcheck vindt trouwens geen overflow van stack variabelen. Het eerste voorbeeld zou die waarschijnlijk wel gedetecteerd hebben. Valgrind ptrcheck mogelijk wel.

[ Voor 10% gewijzigd door user109731 op 09-07-2010 22:44 ]


Acties:
  • 0 Henk 'm!

  • Comp_Lex
  • Registratie: Juni 2005
  • Laatst online: 23:50
Ah ok, nu is het me helemaal duidelijk :)
Pagina: 1