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
Implementatie met context
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
Implementatie
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
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