Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[c++] struct met vector<bool> in class

Pagina: 1
Acties:

  • El_kingo
  • Registratie: Mei 2002
  • Laatst online: 17-03 11:17
Beste proggers,

ik ben nog niet zo heel lang bezig met c++, dus het kan zijn dat ik iets triviaals over het hoofd zie, maar ik heb al een paar dagen getracht een oplossing te vinden, maar het lukt niet...
Het probleem:

Ik heb in een header (zeg network.h) een struct en een class (iets vereenvoudigde weergave, maar veel meer dan dit is het niet):
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
#ifndef NETWORK_H_
#define NETWORK_H_
#include <vector>

struct Computer
    {
        std::vector<bool> isinfected;
    };

class Network {

public:
    Network(int numcomps, char numvirs);
    ~Network();

private:
    char num_virs;
    int m_num_comps;
    Computer *complist;

};


#endif /* NETWORK_H */


De constructor moet een netwerk creeren met een aantal computers (numcomps) en een aantal virussen (numvirs). M.a.w. ik wil kunnen aangeven in mijn hoofdprogramma hoe mijn (theoretische) netwerk eruit ziet,
Mijn implementatie van de constructor:
C++:
1
2
3
4
5
6
7
8
9
Network::Network(int numcomps, char numvirs)
{
    num_virs = numvirs;
    m_num_comps = numcomps;
    complist = new Computer[numcomps];
    for (int i = 0; i < numcomps; ++i) {
        complist[i].isinfected.resize(numvirs,false);
    }
}


In het hoofdprogramma probeer ik vervolgens het netwerk op de volgende manier te initialiseren:
C++:
1
Network compnetwork(numofcomps, numofvirs);

waarbij numofcomps en numofvirs uiteraard locale variabelen zijn van het juiste type en ook geinitialiseerd zijn.

Het probleem is dat het programma crashed op de resize van de vector isinfected in de constructor, en ik heb geen idee waarom...
Het gaat wel goed als ik geen
C++:
1
std::vector isinfected
gebruik in de struct maar bijvoorbeeld een
C++:
1
bool isinfected
(dus maar 1 virus mogelijk op het netwerk)

Als ik een vereenvoudigde versie direct in het hoofdprogramma implementeer gaat het wel goed.
Dus dit doet het wel:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// include alles wat nodig is...
 
struct Computer{
    std::vector<bool> isinfected;
};

int main(int argc, char **argv) {
    Computer *comp;
    comp = new computer[100];
    for (int i = 0; i < 100; ++i) {
        comp[i].isinfected.resize(2,false);
    }
    comp[1].isinfected.at(0) = true;
    for (int i = 0; i < 100; ++i) {
        std::cout << comp[i].isinfected.at(0);
    }
    return 0;
}


Dit werkt gewoon zoals je zou verwachten.

Wie kan mij zeggen wat ik fout doe, want ik snap het niet meer...

Sorry voor de lange post, maar ik hoop dat het zo in ieder geval duidelijk is wat wel en niet goed gaat...
Alvast bedankt voor de moeite! _/-\o_

  • Mijzelf
  • Registratie: September 2004
  • Niet online
Ik denk dat de 'std::vector<bool> isinfected' niet geconstrueerd, omdat Computer een struct is, en dus geen constructor heeft.
Probeer er eens een class van de maken.

  • El_kingo
  • Registratie: Mei 2002
  • Laatst online: 17-03 11:17
Ik denk dat ik snap wat je bedoelt, maar hoe zou deze class eruit moeten zien?
Ik dacht zelf iets als:
C++:
1
2
3
4
5
class Computer
{
    public:
    std::vector<bool> status;
};


maar dan chrashed het programma ook.. (ook als ik de vector private maak en een constructor toevoeg die de vector resized)

  • epic007
  • Registratie: Februari 2004
  • Laatst online: 17-11 15:31
Maf, ik heb je code even gecopy/paste in Visual C++ 2010 en hier werkt het prima. Wat voor waarde heeft numofcomps ? Ik kan me voorstellen dat een negatieve waarde bijvoorbeeld niet werkt.

Ik vroeg me ook af waarom je Computer* complist gebruikt en geen std::vector<Computer>.

  • El_kingo
  • Registratie: Mei 2002
  • Laatst online: 17-03 11:17
Hmm, zou het dan aan de compiler liggen, ik gebruik hier mingw met g++ versie 4.6.2

Edit: zelfs als ik num_of_comps hard in de code zet op 2 of 10 dan draait het niet...

En ik heb inderdaad de Computer* complist al aangepast naar een std::vector<Computer>, ik kwam erachter dat dat makkelijker werkt. (Maar bedankt voor de opmerking!)

Ik zal het (vanavond) eens proberen in Visual C++, die hebben we hier niet op het werk...

Grote Edit:
Ik kwam erachter dat er iets in Eclipse niet goed stond ingesteld voor het builden, hierdoor bleef ik een oude versie draaien die het niet deed...
Hij doet het nu eindelijk op de manier zoals Mijzelf voorstelde (nou ja, ik heb het iets aangepast met een constructor en een setter en getter).
Zo zie je maar weer: het lag niet aan de code maar aan de user (zoals gewoonlijk).
Dank in ieder geval voor het meedenken! _/-\o_

[ Voor 44% gewijzigd door El_kingo op 24-10-2012 14:45 . Reden: Door eigen stupiditeit niet de juiste build.... ]


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 23-11 13:12
Mijzelf schreef op woensdag 24 oktober 2012 @ 13:05:
Ik denk dat de 'std::vector<bool> isinfected' niet geconstrueerd, omdat Computer een struct is, en dus geen constructor heeft.
Probeer er eens een class van de maken.
Een struct is in C++ identiek aan een class, muv het feit dat de default access public is. Afgezien van dat, zou je eens een voorbeeld willen geven waarin een variabele niet 'geconstruct' wordt, want daar ben ik benieuwd naar.

FYI, voor vector<bool> is een alternatief in de C++ library die is geoptimaliseerd voor grootte : std::bitset

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 08:22
std::vector<bool> is óók geoptimaliseerd voor grootte (8 bits per byte enzo). Het verschil tussen std::vector<bool> en std::bitset is dat de grootte van de laatste een template parameter is, en dus een compile-time constante moet zijn. Die kan de TS dus niet gebruiken in deze code.

Gevolg van die optimalisaties is ook dat std::vector<bool> geen “echte” std::vector is; je kunt bijvoorbeeld geen reference/pointer naar een element krijgen. Naar mijn mening kun je meestal beter een std::vector<char> gebruiken, tenzij je serieus geheugen tekort hebt.

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 23-11 13:12
Soultaker schreef op woensdag 24 oktober 2012 @ 15:52:
std::vector<bool> is óók geoptimaliseerd voor grootte (8 bits per byte enzo). Het verschil tussen std::vector<bool> en std::bitset is dat de grootte van de laatste een template parameter is, en dus een compile-time constante moet zijn. Die kan de TS dus niet gebruiken in deze code.

Gevolg van die optimalisaties is ook dat std::vector<bool> geen “echte” std::vector is; je kunt bijvoorbeeld geen reference/pointer naar een element krijgen. Naar mijn mening kun je meestal beter een std::vector<char> gebruiken, tenzij je serieus geheugen tekort hebt.
Je natuurlijk gelijk, het staat er notabene bij :)
Bitsets have a fixed size. For a similar container class that also optimizes for space allocation and allows for dynamic resizing, see the bool specialization of vector (vector<bool>)

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • El_kingo
  • Registratie: Mei 2002
  • Laatst online: 17-03 11:17
Het is geen geheugentekort, ik heb alleen het type gebruikt waarvan ik dacht dat het het meest geschikt is, namelijk een boolean waarde (een comp is wel/niet geinfecteerd). Maar ik begrijp nu dat dat niet de beste manier is in c++, vreemd maar het zal wel aan mij liggen... ;)

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 23-11 13:12
El_kingo schreef op woensdag 24 oktober 2012 @ 17:03:
Het is geen geheugentekort, ik heb alleen het type gebruikt waarvan ik dacht dat het het meest geschikt is, namelijk een boolean waarde (een comp is wel/niet geinfecteerd). Maar ik begrijp nu dat dat niet de beste manier is in c++, vreemd maar het zal wel aan mij liggen... ;)
Als je de post van Soultaker leest dan zou je dat kunnen concluderen, maar ik denk dat in jouw geval een vector<bool> best een goede keus is (tenzij je tegen de genoemde beperkingen aanloopt)

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12:16

.oisyn

Moderator Devschuur®

Demotivational Speaker

.edit: oh wacht ik lees nu pas dat je probleem al opgelost is 8)7

Originele post:

Definieer "het crasht". Hoe crasht het dan? Wordt er een exception gegooid? Krijg je een access violation ("reading from address XXX" oid)?

Met de hier geposte code is in z'n geheel niets mis. Crasht het ook als je programma niets anders doet dan:
C++:
1
2
3
4
5
6
int main()
{
    int numofcomps = 100; // of welke waarden jij ook gebruikt
    int numofvirs = 50;
    Network compnetwork(numofcomps, numofvirs);
}

? Ik gok eerlijk gezegd van niet. Als dat inderdaad niet het geval is, dan gooi ik het op heap corruption. Ergens in je programma doe je een van de volgende dingen:
  • Je schrijft buiten de boundaries van een array
  • Je schrijft naar een object dat je al gedeletet hebt (dangling pointer)
  • Je deletet een object dat je al gedeletet hebt (dangling pointer)
  • Je deletet een object dat je nooit geconstruct hebt (uninitialized pointer)
Hierdoor kan de interne boekhouding van de geheugenallocator stuk gaan, waardoor het vervolgens crasht bij een geheel ongerelateerde geheugenallocatie of deallocatie.

[ Voor 4% gewijzigd door .oisyn op 25-10-2012 01:30 ]

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.


  • Gehakt
  • Registratie: Juli 2002
  • Laatst online: 24-10 20:19
C++:
1
2
3
4
5
Computer *comp; 
    comp = new computer[100]; 
    for (int i = 0; i < 100; ++i) { 
        comp[i].isinfected.resize(2,false); 
    } 

Moet je hier niet de pointer in de array dereferencen op deze manier?
C++:
1
    comp[i]->isinfected.resize(2,false); 

Ik kan me voorstellen dat je code nu wel werkt omdat je value objecten van het type Computer in een std::list gebruikt.

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 23-11 13:12
comp[ i ] ( lees als *(comp + i) ) levert een Computer op, niet een Computer*

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • El_kingo
  • Registratie: Mei 2002
  • Laatst online: 17-03 11:17
.oisyn schreef op woensdag 24 oktober 2012 @ 19:31:
*snip*

? Ik gok eerlijk gezegd van niet. Als dat inderdaad niet het geval is, dan gooi ik het op heap corruption. Ergens in je programma doe je een van de volgende dingen:
  • Je schrijft buiten de boundaries van een array
  • Je schrijft naar een object dat je al gedeletet hebt (dangling pointer)
  • Je deletet een object dat je al gedeletet hebt (dangling pointer)
  • Je deletet een object dat je nooit geconstruct hebt (uninitialized pointer)
Hierdoor kan de interne boekhouding van de geheugenallocator stuk gaan, waardoor het vervolgens crasht bij een geheel ongerelateerde geheugenallocatie of deallocatie.
Door het vele debuggen en proberen en vervolgens (door mijn eigen fout) niet de juiste executable te gebruiken zou ik niet meer precies de originele code weten... Maar ik gok dat ik inderdaad ergens anders een heap corruption heb veroorzaakt! Beginnersfoutje zullen we maar zeggen :P.
Het lijkt nu in ieder geval opgelost!
Pagina: 1