[C/C++] Crash na std::cin

Pagina: 1
Acties:

  • Hans1990
  • Registratie: Maart 2004
  • Niet online
Hey,

Ik ben nog een beginnende C/C++'er en bedacht dat het een leuke oefening is om structs, klassen, I/O etc. onder de knie te krijgen door een DOS applicatie te schrijven voor het beheren van addressen.

Nou wil ik die vergrendelen dus schrijf ik een login systeem. Al gauw kwam ik met het volgende probleem:

Ik vraag bij het inloggen op gebruikersnaam en wachtwoord. Echter heb ik de code voor het ophalen (en opslaan) nog niet gemaakt. Vanwege dat heb ik het zo gemaakt; als de gebruikersnaam is opgegeven en het systeem erachter komt er geen gebruikers in de database zijn krijg je een melding dat er geen gebruikers zijn en je kan je nog een wachtwoord kan invullen. Indien het wachtwoord is ingevuld word er gevraagd of de gebruiker dit account wilt aanmaken. Hier valt y of n voor op te geven. Indien n word opgegeven word er gevraagd voor opnieuw proberen (Als ik daar dus ook n op geef laat ik het programma afsluiten). Indien ik y opgeef doet het nog niks (en laat ik het programma afsluiten). De resultaten van de vragen waar de gebruiker y of n op kan antwoorden worden in een string opgeslagen en met cin >> variable gedaan.

Nu is het probleem: In beide gevallen als ik het programma laat afsluiten crasht het programma. Ik krijg wel scherm van Just in time debugger van Visual studio maar ik heb het gecompiled met Dev-Cpp 4.9.8.0 (en anders wel MSYS/MinGW) en zit er blijkbaar geen debug informatie bij (en anders zeurt visual studio om: No sourcefile). In beide gevallen krijg ik een crash. En in Visual studio (2005) krijg ik zelfs hem niet eens aan het compilen omdat raar genoeg de libraries van visual studio ervan foute syntax hebben (net een clean install) 8)7 en krijg ik +/- 300 - 400 errors.

Omdat Visual de source niet heeft kan ik niet kijken waar de fout optreed. Daarom plaats ik min probleem hier. Omdat de sourcecode inmiddels al >300 regels is heb ik maar even de sourcecode op een SVN server gezet:

https://opensvn.csie.org/...wser/addressManager/trunk

Legenda wat er per bestand zit:
addressManager.h: -empty-
addressMaganger.c: Basis van het progamma. Volgens mij hoort dit te werken, natuurlijk kan je het checken want zoveel ervaring met C++ heb ik ook weer niet ;)
auth.h: Hierin word de klasse loginSession gedefineerd. Deze bevat dus o.a. het afhandelen van het login form
auth.c: Hier in staat de code voor het login form. Functie is: doLoginForm op regel 44.
io.c: Wat replica's van print() functie
io.h: Definitie's van de replica's van print() functie
user.c: Bevat code voor de klasse usersRoot die verantwoordelijk is voor het listen van gebruikers (nog niet werkend; slechts hard ingeprogrammeerde voorbeelden gebruikt. Momenteel: geen gebruikers)
user.h Definitie voor de klasse usersRoot.

Ik heb ook op het forum zitten zoeken natuurlijk. Daar sprak met over iets van dat het type niet kan worden geconverteerd. Daar sprak men meer over ints en dat de enter er niet bij hoort dus crash. Ik gebruikte eerst char voor de N en Y opgaves maar had zelf nog uitbugt dat dat string moet zijn. Het werkte toen ff en nu niet meer :'( .

Iemand een oplossing voor deze beginnende C/C++'er in nood ? :+

[ Voor 9% gewijzigd door Hans1990 op 05-01-2006 21:55 ]


  • Daos
  • Registratie: Oktober 2004
  • Niet online
Een beginner begint normaal met een code van een paar regels. Meer is te moeilijk omdat ze nog maar beginner zijn.

Debuggen gaat makkelijker als je functies niet te groot zijn. Meer dan 100 regels is te veel voor een functie. Die moet je splitsen.

Geef eens een paar (< 5) foutmeldingen die je krijgt in VC. Zonder debugger is het lastig programmeren.
Je kan ook een paar keer wat statusinfo printen in je code. Je kan dan zien waar het mis gaat.

  • Hans1990
  • Registratie: Maart 2004
  • Niet online
Voornamelijk dit in VC:
Error 1 error C2143: syntax error : missing '{' before ':' E:\Program Files\Microsoft Visual Studio 8\VC\include\cstdio 25
Error 2 error C2059: syntax error : ':' E:\Program Files\Microsoft Visual Studio 8\VC\include\cstdio 25
Error 3 error C2143: syntax error : missing '{' before ':' E:\Program Files\Microsoft Visual Studio 8\VC\include\cstdio 25
Error 4 error C2059: syntax error : ':' E:\Program Files\Microsoft Visual Studio 8\VC\include\cstdio 25
Error 5 error C2143: syntax error : missing '{' before ':' E:\Program Files\Microsoft Visual Studio 8\VC\include\cstdio 25
Error 6 error C2059: syntax error : ':' E:\Program Files\Microsoft Visual Studio 8\VC\include\cstdio 25
Error 7 error C2143: syntax error : missing '{' before ':' E:\Program Files\Microsoft Visual Studio 8\VC\include\cstdio 26
Error 8 error C2059: syntax error : ':' E:\Program Files\Microsoft Visual Studio 8\VC\include\cstdio 26
Error 9 error C2143: syntax error : missing '{' before ':' E:\Program Files\Microsoft Visual Studio 8\VC\include\cstdio 26
Error 10 error C2059: syntax error : ':' E:\Program Files\Microsoft Visual Studio 8\VC\include\cstdio 26

Dat ongeveer 40x dus. Het is niet mijn code. Wat ik heb gedaan is: Ik heb een nieuw project gemaakt (leeg Visual C++ project) en daar mijn header & source files ingezet. Ik heb dan gewoon op Start debugging gedrukt en kreeg dus deze errors.

Nouja, ik ben nog een beginner ik het maken van wat grotere programma's. Ik heb natuurlijk wel wat testje's gemaakt met simpele apps met structs, klassen etc.

Verwijderd


[ Voor 99% gewijzigd door Verwijderd op 06-01-2006 09:46 ]


  • Hans1990
  • Registratie: Maart 2004
  • Niet online
Blaatkoetje: Euhm, volgens mij is een syntax error toch wat anders?

En waarom zou mijn programma het in 2 compilers wel doen en in VC niet. En ik include ook helemaal niets als cstdio ofzo (kijk maar in SVN trunk) want dat lijkt VC er ook wel gewoon bij te verzinnen :X

Verwijderd

In de destructor van usersRoot doe je een delete op allUsers, wat je niet mag doen.

edit: je gebruikt allUsers sowieso verkeerd. Je kunt beter een vector gebruiken ipv. array.

[ Voor 37% gewijzigd door Verwijderd op 06-01-2006 00:33 ]


  • TheNameless
  • Registratie: September 2001
  • Laatst online: 07-02-2025

TheNameless

Jazzballet is vet!

Ik heb hier even wat geprobeerd te compilen maar volgens mij ligt het aan het gebrek van UTF8 encoded files. Kan het zijn dat de bestanden opgeslaan zijn als UTF8? Want dan interpreteerd VC de spaties en ook enters en tabs niet goed.

Ducati: making mechanics out of riders since 1946


  • moto-moi
  • Registratie: Juli 2001
  • Laatst online: 09-06-2011

moto-moi

Ja, ik haat jou ook :w

Hans1990 schreef op Thursday 05 January 2006 @ 23:20:
En waarom zou mijn programma het in 2 compilers wel doen en in VC niet. En ik include ook helemaal niets als cstdio ofzo (kijk maar in SVN trunk) want dat lijkt VC er ook wel gewoon bij te verzinnen :X
Ligt eraan welke versie van VC je het over hebt :P
6 was nou niet bepaald compatible met ansi , met 7 en verder schijnt dat een stuk beter te zijn :)

God, root, what is difference? | Talga Vassternich | IBM zuigt


  • Jaap-Jan
  • Registratie: Februari 2001
  • Nu online
Ik heb je code bekeken, maar ik krijg al met al geen goede indruk. Er zijn nog veel te veel beginnersfoutjes. Je bent al redelijk objectgeoriënteerd bezig, maar je hebt de basis van het programmeren nog niet onder de knie lijkt het :).

Ik begin met addressManager.c:
C++:
1
2
bool doLogin(loginSession &session);
void startProgram(loginSession &session);
Sowieso horen je prototypes in je header- file, maar waarom heb je ook een prototype voor je main()- functie? Als ik een programma zou schrijven zou ik bijvoorbeeld bovenstaande twee regels gebruiken en daarna beginnen met het definiëren van int main(). Na de main() komen dan de twee functies terug die je bovenaan in je programma hebt gedeclareerd.

C++:
1
if (session.isLoggedIn() == false)
Nooit doen zo. Dit is een slechte programmeergewoonte. Je hebt al een boolean in session.isLoggedIn(), waarom ga je dan nog kijken of die false is? Gebruik die boolean gewoon direct in je statement:
C++:
1
if (!session.isLoggedIn())


Daarna roep je doLogin(session) aan. Die controleert op zijn beurt weer of session.isLoggedIn() niet false is? Waar is dat voor nodig? Dat had je net toch ook al gecheckt in main()? Als we die dubbele check weghalen krijgen we dit:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
    bool doLogin(loginSession session)
    {
            bool returnResult = true;
    
             int result = session.doLoginForm();
                   
            if (result == 1)
                     returnResult = true;
            else
                     returnResult = false;
           
            return returnResult;
    }
Nog steeds verschrikkelijk omslachtig, dit kan ingekort worden tot 2 statements waarmee je exact hetzelfde bereikt:
C++:
1
2
3
4
5
    bool doLogin(loginSession session)
    {
             int result = session.doLoginForm();
            return (result == 1);
    }
Maar daarmee heb je zo'n beetje het hele bestaansrecht van doLogin() afgenomen, want je kunt dit ook direct in main() doen:
C++:
1
2
3
4
5
            // Is there a login session already?
            if (session.isLoggedIn() == false)
                    result = (session.doLoginForm() == 1);
            else
                    result = true;
Oké, verder met auth.c.
C++:
1
2
        // reset the session ID to -1. That means 'no session started'
        loginSessionID = -1;
Hoezo loginSessionID? Wat bedoel je daarmee? Ik kan me voorstellen dat je een loginSession wilt opzetten, maar één loginSession kan toch geen ID hebben? Een sessie kan wel een status hebben zoals gelukt of niet gelukt, maar een sessie een ID geven krijg je pas als je een class hebt die meerdere sessies beheert, bijvoorbeeld in een Vector of een simpele Array.

Hetzelfde geldt eigenlijk voor je user.c: maak duidelijk onderscheid tussen 1 user (die bijvoorbeeld een naam en een wachtwoord kan hebben) en een lijst van users, die de users beheert. Als je die userlijst duidelijke functies geeft die je kunnen helpen (bijvoorbeeld functies om een user op te zoeken aan de hand van een gebruikersnaam, users toe te voegen en te verwijderen). Bij een functie als getUsers() stel ik me voor dat alle users in één keer opvraagt. Tot zover even genoeg over de bedoeling van classes.
C++:
1
2
3
4
5
6
7
bool loginSession::isLoggedIn()
    {
        if (loginSessionID == -1)
            return false;
       
        return true;
    }
Dit is weer hetzelfde als net, kan in één regel:
C++:
1
bool loginSession::isLoggedIn() { return !(loginSessionID == -1); }
En dit is precies de reden dat je een loginSession beter een status kunt laten geven, want dan kun je inLoggedIn() gewoon die boolean laten returnen. Een user is ingelogd of niet.

C++:
1
2
if (isLoggedIn() == true)
                    return false;
Is het niet makkelijker om zelf naar die variabele te kijken? isLoggedIn() is leuk voor externe classes die de status op willen vragen, maar deze functie zit in dezelfde class en heeft gewoon direct toegang tot de status:
C++:
1
2
if (!(loginSessionID == -1))
                    return false;
Voor het wijzigen van een variabele zou wel een functie aanspreken in plaats van de variabele direct te wijzigen, want dan kun je in die functie veiligheidscontroles uitvoeren

Je codeerstijl is voor de rest wel goed, de code is opzich wel overzichtelijk, alleen mis je nog duidelijk een basis. Ik weet niet wat je tot nu toe hebt gedaan om het programmeren onder de knie te krijgen, maar een goed boek zou geen overbodige luxe zijn. Je maakt nog erg veel beginnersfoutjes en schrijft code die vele malen efficiënter kan.

Als je bijvoorbeeld een loginsysteem wilt maken, dan kun je bijvoorbeeld een klassendiagram maken als deze: Afbeeldingslocatie: http://members.home.nl/jjvdveen/got/UML.png Hier begin je simpel met een User die een wachtwoord en een naam kan hebben. De naam en het wachtwoord zijn aan te passen door middel van de getters (accessors) en setters (mutators). Hierdoor kunnen gebruikers worden gemaakt en opgevraagd

Vervolgens de klasse UserList. Hier kun je gebruikers opvragen met getUser() (deze kan bijvoorbeeld null teruggeven als een gebruiker niet kan worden gevonden) en toevoegen en verwijderen met respectievelijk addUser() en deleteUser() zodat je gebruikers kunt toevoegen aan de UserList die bijvoorbeeld uit een configuratiebestand komen.

findUserName() is handig om te kijken of een bepaalde gebruiker al bestaat, bijvoorbeeld bij het inloggen. getUsersFromFile() voegt gebruikers toe vanuit een bestand.

Tot slot heb je de LoginSession. Op dit moment heeft die de UserList, zodat je een doLogin() kunt doen. doLogin() kan dan checken of het wachtwoord en de naam kloppen door de gebruiker op te vragen met getUser() en als hij bestaat (dus getUser() is niet null) het password checken. Als het wachtwoord correct is wordt de status (die standaard op false staat) natuurlijk aangepast.

Dit is bijvoorbeeld een manier waarop je zoiets aan kunt pakken, maar het idee is dat je classes duidelijk zijn. Classes zijn objecten en objecten kunnen eigenschappen (de variabelen) en gedragingen (de functies) hebben.

Ik hoop dat je wat aan mijn tips hebt, de strekking is eigenlijk: begin bij het begin en maak het jezelf stapje voor stapje moeilijker, in plaats van meteen in het diepte te springen :).

[ Voor 9% gewijzigd door Jaap-Jan op 06-01-2006 11:45 ]

| Last.fm | "Mr Bent liked counting. You could trust numbers, except perhaps for pi, but he was working on that in his spare time and it was bound to give in sooner or later." -Terry Pratchett


  • schoene
  • Registratie: Maart 2003
  • Laatst online: 11:39
Japie_17 schreef op vrijdag 06 januari 2006 @ 02:31:

Ik begin met addressManager.c:
C++:
1
2
bool doLogin(loginSession &session);
void startProgram(loginSession &session);
Haal die '&' eens weg, dat is als je met pointers gaat werken.
Dat is helemaal niet waar. LoginSession &session is een referentie naar een bestaande session. Als je de referentie weg haalt, wordt een kopie gemaakt van de session, en worden de wijzigingen aan session in doLogin () niet toegepast op de session aangemaakt in de main, maar op een lokale kopie ervan. En dat zal zeker de bedoeling niet zijn. Die referentie moet er dus wel degelijk staan. Volgens mij ben jij een beetje verward met het meegeven van pointers in functies (zoals het in c zou gebeuren en niet in c++):
C:
1
2
3
4
5
6
7
8
9
10
bool doLogin (loginSession *session)
{
/*...*/
}

int main ()
{
LoginSession session;
doLogin (&session);
}

  • Hans1990
  • Registratie: Maart 2004
  • Niet online
Hartelijk bedankt voor jullie hulp. Ik zal eerst mijn programma code eens terug brengen naar 'back to basics' en als het dan niet lukt hier weer een reactie plaatsen.

En ik heb even gekeken waar ik mijn C bestanden als op sla: ANSI.. Met notepad 2 werk ik namelijk. Dev-Cpp heeft een brakke indent engine en visual studio vind ik eigenlijk een veels te omslachtige ontwikkelings omgeving (teveel knopje's en datje's en ik wil eigenlijk liever lekker eigenwijs dingen zelf leren schrijven ipv .NET framework gebruiken).

  • Jaap-Jan
  • Registratie: Februari 2001
  • Nu online
schoene schreef op vrijdag 06 januari 2006 @ 09:14:
[...]


Dat is helemaal niet waar. LoginSession &session is een referentie naar een bestaande session. Als je de referentie weg haalt, wordt een kopie gemaakt van de session, en worden de wijzigingen aan session in doLogin () niet toegepast op de session aangemaakt in de main, maar op een lokale kopie ervan. En dat zal zeker de bedoeling niet zijn. Die referentie moet er dus wel degelijk staan. Volgens mij ben jij een beetje verward met het meegeven van pointers in functies (zoals het in c zou gebeuren en niet in c++):
C:
1
2
3
4
5
6
7
8
9
10
bool doLogin (loginSession *session)
{
/*...*/
}

int main ()
{
LoginSession session;
doLogin (&session);
}
Ik was daar inderdaad mee in de war, het is gewoon call by reference, stom |:(.

| Last.fm | "Mr Bent liked counting. You could trust numbers, except perhaps for pi, but he was working on that in his spare time and it was bound to give in sooner or later." -Terry Pratchett


  • Daos
  • Registratie: Oktober 2004
  • Niet online
Wat crasht er bij jou? Ik krijg bij mij (Dev-C++4) gewoon dit:
code:
1
2
3
4
5
6
7
8
9
10
11
12
You aren't logged in yet. Please do so:
Username: fgdgdfgfd
       There are no users in the database. Fill in a password to create one
Password: sdgfdsg
Are you sure want to create a user with this password? (y/n)y
You aren't logged in yet. Please do so:
Username: grdsgdfgr
       There are no users in the database. Fill in a password to create one
Password: grdegfdge
Are you sure want to create a user with this password? (y/n)n
Retry ?n
Terminating programProgram started.Druk op een toets om door te gaan. . .

Verwijderd

Zoals ik al zei; hij crasht op het vrijgeven van allUsers, in de destructor van usersRoot (user.c). Je mag dit helemaal niet vrijgeven en daarom crasht-ie:

C:
1
2
3
4
5
6
7
8
9
class usersRoot {
public:
  ~usersRoot() {
    delete allUsers;
  }

private:
  userObj allUsers[];
}


Haal de regel delete allUsers maar weg uit de destructor, dan crasht hij niet meer.

  • Daos
  • Registratie: Oktober 2004
  • Niet online
Om het in VC++ enigszins werkend te krijgen moet je waarschijnlijk alle .c-bestanden hernoemen naar .cpp.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 11:53

.oisyn

Moderator Devschuur®

Demotivational Speaker

Hoi Hans1990,

kun je voortaan je relevante code gewoon hier posten, tussen [code=c++]...[/code] tags? Gewoon de 10-20 regels rond de foutmelding van de compiler, en evt. nog functie- en typedefinities die van belang kunnen zijn. Als je wilt dat wij je helpen kun je het ons natuurlijk beter zo gemakkelijk mogelijk maken, sommige mensen haken namelijk al af als ze je hele code door moeten gaan spitten :)

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.


  • Hans1990
  • Registratie: Maart 2004
  • Niet online
@ .oisyn: Als je mijn bericht helemaal had gelezen had je kunnen opmaken dat ik niet weet waar precies de fout zat in mijn code (en dus ook niet weet wat ik precies moet posten, dus alles maar gedaan. Ik dacht dat het overzichtelijker was om gewoon alles in een SVN trunk te zetten), dat er geen foutmelding kwam van de compiler behalve in VC (die ik niet gebruik eigenlijk) etc. Maargoed, zal het de volgende keer wel anders doen ;)

@playroll: Ik heb dat even gedaan en opeens werkt het nu wel. Dank u _/-\o_

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Japie_17 schreef op vrijdag 06 januari 2006 @ 02:31:
Ik heb je code bekeken, maar ik krijg al met al geen goede indruk. Er zijn nog veel te veel beginnersfoutjes. Je bent al redelijk objectgeoriënteerd bezig, maar je hebt de basis van het programmeren nog niet onder de knie lijkt het :).
Lijkt me een terechte conclusie, gezien de topic titel. C en C++ zijn twee verschillende talen, en de eerste is niet geschikt voor OO.
Sowieso horen je prototypes in je header- file
Nee, dat is niet waar. Als ik een paar recursieve functies f en g heb, dan is er op zich geen reden om een prototype in een header te zetten, maar de laatst gedefinieerde zal een prototype nodig hebben voorafgaand aan de definitie van de eerste.

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


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
MayaFreak schreef op vrijdag 06 januari 2006 @ 00:02:
Ik heb hier even wat geprobeerd te compilen maar volgens mij ligt het aan het gebrek van UTF8 encoded files. Kan het zijn dat de bestanden opgeslaan zijn als UTF8? Want dan interpreteerd VC de spaties en ook enters en tabs niet goed.
Tuurlijk wel, een ASCII spatie is 0x20 is een UTF-8 spatie, en hetzelfde geld voor alle ASCI karakters. Dat is het hele idee achter UTF-8, en het verschil met UTF-18

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


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
moto-moi schreef op vrijdag 06 januari 2006 @ 00:11:
[...]
Ligt eraan welke versie van VC je het over hebt :P
6 was nou niet bepaald compatible met ansi , met 7 en verder schijnt dat een stuk beter te zijn :)
Ik denk VC8, tenzij hij z'n VC6 geinstalleerd heeft in C:\Program Files\Microsoft Visual Studio 8 ;)

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


  • Hans1990
  • Registratie: Maart 2004
  • Niet online
In mijnopic start bericht staat nog wel welke versie ik heb: Visual studio 2005... dat is V8 ;)

Ik heb trouwens ook even mijn bestanden naar .cpp gerenamed en nu compilede die wel met wat aanpassingen (ouwere versie) van o.a. delete allUsers. Toen geen errros maar eigenlijk komt het als een beetje mosterd na de maaltijd, ik ga toch mijn programma wat herschrijven.

[ Voor 25% gewijzigd door Hans1990 op 06-01-2006 22:32 ]

Pagina: 1