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

[C++] Illegal Intruction tijdens fprintf()

Pagina: 1
Acties:

  • jvaneijk
  • Registratie: Mei 2003
  • Laatst online: 29-05 12:10
Tijdens het uitvoeren van mijn programma wil ik wat data naar een bestand schrijven.
De variabelen die ik wegschrijf zijn allen gevuld.
Als ik echter fprintf() aanroep met de variabelen dan krijg ik een illegal intruction,
zet ik echter hard de waardes in de fprintf() dan gaat het gewoon goed heeft iemand enig idee?

Ik heb al gezocht op het forum en op google. maar ik kan niet echt ontdekken wat het probleem kan zijn of wat die illegal instruction inhoud

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
FILE* pFile3;
    pFile3 = fopen(str1.c_str(),"w");
    TRACE(fname);
    TRACE(patci.dimx);
    fprintf(pFile3, "%s\n %i\n %i\n %i\n %f\n %f\n %f\n %f\n %f\n %f",
            //"anon1",
            fname,
            //109,
            patci.dimx,
            //63,
            patci.dimy,
            //106,
            patci.dimz,
            //0.0,
            patci.xtable[0]-0.5*patci.psizex,
            //0.0,
            patci.ytable[0]-0.5*patci.psizey,
            //0.0,
            patci.ztable[0]-0.5*patci.psizez,
            //0.382168,
            patci.psizex*patci.dimx,
            //0.220886,
            patci.psizey*patci.dimy,
            //0.159000);
            patci.psizez*patci.dimz);
    fclose(pFile3);

de uitgecommentarieerde delen werken wel maar als ik het dus via de variabelen doe krijg ik illegal instruction melding.

iRacing Profiel


  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Lukt het je om het probleem wat meer te isoleren? Als je een voor 1 de waardes uitcomment bij welke waarde zit het probleem dan?

Weet je zeker dat fname bijvoorbeeld een terminated string is?

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


  • leuk_he
  • Registratie: Augustus 2000
  • Laatst online: 01-11 22:03

leuk_he

1. Controleer de kabel!

waarschijnlijk kloppen de typen van de variablen niet met de %f enzo, waardoor het aantal variablen op de stack niet overeenkomt met de format string.

Oplossing(om te testen): alle vars casten naar juiste type.

Need more data. We want your specs. Ik ben ook maar dom. anders: forum, ff reggen, ff topic maken
En als je een oplossing hebt gevonden laat het ook ujb ff in dit topic horen.


  • Stukfruit
  • Registratie: Oktober 2007
  • Niet online
Het eerste dat in me opkomt: weet je zeker dat het vermenigvuldigen van integers een float oplevert?

Als ik goed heb gelezen tenminste, ik durf het bijna niet meer met jouw posts :+, zijn de variabelen uit patci integers, aangezien je die eerder ook zo wegschrijft..

edit:
argh, ik moet sneller de verstuurknop indrukken..

[ Voor 10% gewijzigd door Stukfruit op 11-04-2008 12:49 ]

Dat zit wel Schnorr.


  • jvaneijk
  • Registratie: Mei 2003
  • Laatst online: 29-05 12:10
rwb schreef op vrijdag 11 april 2008 @ 12:12:
Lukt het je om het probleem wat meer te isoleren? Als je een voor 1 de waardes uitcomment bij welke waarde zit het probleem dan?

Weet je zeker dat fname bijvoorbeeld een terminated string is?
Ik heb zojuist het probleem geprobeerd te isoleren en hij gaat bij de eerste waarde (de string) al fout. Hoe kom ik erachter of het een terminated string is? En waarom maakt dit uit?

iRacing Profiel


  • jvaneijk
  • Registratie: Mei 2003
  • Laatst online: 29-05 12:10
Stukfruit schreef op vrijdag 11 april 2008 @ 12:49:
Het eerste dat in me opkomt: weet je zeker dat het vermenigvuldigen van integers een float oplevert?

Als ik goed heb gelezen tenminste, ik durf het bijna niet meer met jouw posts :+, zijn de variabelen uit patci integers, aangezien je die eerder ook zo wegschrijft..

edit:
argh, ik moet sneller de verstuurknop indrukken..
patci is een Object patientCubeInfo hierin staan verschillende variabelen die informatie bevatten over CT-data
de dimx, dimy en dimz zijn short ints
psizex. y en z zijn floats
xtable is een vector van floats zelfde geldt voor y en z

iRacing Profiel


  • leuk_he
  • Registratie: Augustus 2000
  • Laatst online: 01-11 22:03

leuk_he

1. Controleer de kabel!

jvaneijk schreef op vrijdag 11 april 2008 @ 12:49:
[...]


Ik heb zojuist het probleem geprobeerd te isoleren en hij gaat bij de eerste waarde (de string) al fout. Hoe kom ik erachter of het een terminated string is? En waarom maakt dit uit?
Wat denk je zelf: wat denk je dat er in de variable fname zit ?(die TRACE macro daarboven logt hem vst ergens...). Niet null terminataed, print geheugen locaties tot een 0 string, zelfs voorbijde hoeveelheid geheugen gealloceerd voor fname. (als deze niet all NULL is) .

Ben bang dat je wellicht beter een stukje over C & strings kunt zoeken.

Need more data. We want your specs. Ik ben ook maar dom. anders: forum, ff reggen, ff topic maken
En als je een oplossing hebt gevonden laat het ook ujb ff in dit topic horen.


  • jvaneijk
  • Registratie: Mei 2003
  • Laatst online: 29-05 12:10
leuk_he schreef op vrijdag 11 april 2008 @ 13:09:
[...]


Wat denk je zelf: wat denk je dat er in de variable fname zit ?(die TRACE macro daarboven logt hem vst ergens...). Niet null terminataed, print geheugen locaties tot een 0 string, zelfs voorbijde hoeveelheid geheugen gealloceerd voor fname. (als deze niet all NULL is) .

Ben bang dat je wellicht beter een stukje over C & strings kunt zoeken.
TRACE is een predef. die een simpele cout doet op de var tussen de haakjes. TRACE(fname); geeft netjes anon1 dit zit er ook netjes in tenminste dat heb ik er zelf ingeplaatst.

Dit doe ik met fname
C++:
1
2
3
4
size_t found;
    found = patFname.find_last_of("/");
    std::string fname;
    fname = patFname.substr(found+1);

[ Voor 10% gewijzigd door jvaneijk op 11-04-2008 13:23 ]

iRacing Profiel


Verwijderd

dan zul je niet fname moeten printen, maar fname.c_str()

  • jvaneijk
  • Registratie: Mei 2003
  • Laatst online: 29-05 12:10
Verwijderd schreef op vrijdag 11 april 2008 @ 13:26:
dan zul je niet fname moeten printen, maar fname.c_str()
Damn... STRING / CHAR ARRAYS moeten niet gebruikt worden in C/C++ hou die taal lekker voor alles en nog wat maar ga geen gebruik maken van strings :S

iRacing Profiel


Verwijderd

Probeer eerst ff een sprintf(), dan weet je zeker dat het omzetten geen problemen geeft, fprintf() maakt waarschijnlijk gebruik van dezelfde vsnprintf() (oid, lang geleden) functie als bij sprintf(), kun je dat iig al uitsluiten. :)

Verwijderd

jvaneijk schreef op vrijdag 11 april 2008 @ 13:29:
[...]

Damn... STRING / CHAR ARRAYS moeten niet gebruikt worden in C/C++ hou die taal lekker voor alles en nog wat maar ga geen gebruik maken van strings :S
Naja, het is meer een kwestie van weten waar je mee bezig bent.

Net als wanneer je met geladen vuurwapens speelt :)

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 08:45

.oisyn

Moderator Devschuur®

Demotivational Speaker

jvaneijk schreef op vrijdag 11 april 2008 @ 13:29:
[...]

Damn... STRING / CHAR ARRAYS moeten niet gebruikt worden in C/C++ hou die taal lekker voor alles en nog wat maar ga geen gebruik maken van strings :S
En in het vetgedrukte gedeelte zit je probleem. C/C++ is geen taal. En C is geen C++. std::string is C++. de printf* style functies zijn C. Omdat jij er zelf voor kiest om C en C++ te mixen, moet je extra goed opletten waar je mee bezig bent. Als je gewoon van C++'s iostreams gebruik had gemaakt dan had je dit probleem nooit gehad :)

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.


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 14:39
Ik weet niet wat voor compiler je gebruikt, maar met GCC krijg ik gewoon de melding: cannot pass objects of non-POD type 'struct std::string' through '...'; call will abort at runtime en dat is ook precies wat er gebeurt. ;)

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 08:45

.oisyn

Moderator Devschuur®

Demotivational Speaker

GCC is ruk, het mag namelijk gewoon :). Van de zotte dat dat abort at runtime. Het enige wat ie hoeft te doen is een binary copy van het geheugen van de std::string. Valide ISO C++ en hoeft dus niet eens een warning op te leveren.

Comeau geeft twee warnings. Eentje die je waarschuwt voor het feit dat je een non-POD passed, en nog een omdat het type dat je meegeeft niet compatible is met %s. Die tweede is natuurlijk een special case voor printf(), als ik een eigen functie maak die precies hetzelfde doet krijg ik die warning niet ;)

[ Voor 55% gewijzigd door .oisyn op 11-04-2008 18: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.


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 14:39
Ik heb vertrouwen in GCC, en dus de standaard (of eigenlijk een oude draft) er op nageslagen:
When there is no parameter for a given argument, the argument is passed in such a way that the receiving function can obtain the value of the argument by invoking va_arg. [..] If the argument has a non-POD class type, the behavior is undefined.
Is dit in nieuwere versies van de standaard wel toegestaan? (If so, hoe kom ik aan recente taaldocumentatie zonder veel geld op tafel te leggen?)

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 08:45

.oisyn

Moderator Devschuur®

Demotivational Speaker

Je kijkt naar het verkeerde stuk, namelijk naar het uitlezen van de vararg vars. Dat dat undefined is als je er een std::string in stopt geloof ik direct op je woord :). Dat is echter niet wat GCC zegt.

Overigens ben ik nu wel benieuwd waar de abort eigenlijk vandaan komt. Het passen van de std::string aan printf(), of het uitlezen van die data in printf().

Verder
[google=ISO/IEC 14882:1998 pdf]
[google=ISO/IEC 14882:2003 pdf]
:P

[ Voor 9% gewijzigd door .oisyn op 11-04-2008 18:20 ]

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.


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 14:39
GCC genereert gewoon opzettelijk een illegal instruction.
Als ik bijvoorbeeld deze code heb:
C++:
1
2
3
4
#include <string>
extern std::string s;
void foo(...);
void test() { foo(123); }

Dan genereert 'ie voor test de volgende code:
code:
1
2
3
4
5
6
7
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   83 ec 08                sub    $0x8,%esp
   6:   c7 04 24 7b 00 00 00    movl   $0x7b,(%esp)
   d:   e8 fc ff ff ff          call   e <_Z4testv+0xe>  ; foo
  12:   c9                      leave
  13:   c3                      ret


Logisch. Verander ik nu het argument van 123 naar s, dan genereert 'ie dit:
code:
1
2
3
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   0f 0b                   ud2a

Hij maakt niet eens de functiedefinitie meer af, maar produceert een ongeldige instructie. Lijkt er dus op dat dit gedrag wel opzettelijk is.

Overigens kwam het stukje wat ik quotte uit hoofdstuk 5.2.2, Function call, alinea 7; dat lijkt wel degelijk te gaan over function calling (en niet over het uitlezen van varargs, wat natuurlijk fout gaat als je een argument met een verkeerd type probeert te benaderen).

[ Voor 12% gewijzigd door Soultaker op 11-04-2008 19:05 ]


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 16-11 18:33
Je kijkt naar het verkeerde stuk, namelijk naar het uitlezen van de vararg vars ...
Volgens mij gaat paragraaf 7 over het geval waar er voor een argument geen parameter is, en volgens mij kan dat alleen geldig zijn in het geval van het gebruik van een ellipsis ( Zie paragraaf 6 ) in de parameterlist.

fprintf gebruikt een ellipsis voor zijn argumenten, dus het stuk dat Soultaker quote is wel degelijk van toepassing.

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: 08:45

.oisyn

Moderator Devschuur®

Demotivational Speaker

.edit: nvm, ik las verkeerd. Jullie hebben idd gelijk.

[ Voor 76% gewijzigd door .oisyn op 13-04-2008 22:21 ]

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.


  • jvaneijk
  • Registratie: Mei 2003
  • Laatst online: 29-05 12:10
Om even terug te komen op dat ik zelf ervoor kies om C / C++ met elkaar te mengen dat is niet helemaal waar. Mijn gedeelte is compleet C omdat dat niet anders kan andere mensen zijn zo vriendelijk geweest om hun code in C++ aan te leveren. En dat geeft nogal problemen.

iRacing Profiel


  • Stukfruit
  • Registratie: Oktober 2007
  • Niet online
Kan je dan niet gewoon beter een wrapper schrijven?

Dat zit wel Schnorr.


  • sam.vimes
  • Registratie: Januari 2007
  • Laatst online: 08-06 08:44
Ik denk dat de membervariabelen patci.psizex, patci.dimx, patci.psizey, patci.dimy, patci.psizez, patci.dimz van het type int zijn. (Dit is een veronderstelling, je geeft nl. niet voldoende info.) Het product patci.psizex*patci.dimx etc. is daardoor ook van het type int. Dit type is 4 bytes lang. Echter, het printf-format %f verwacht een waarde van het type double met lengte 8 bytes. Daardoor lees je buiten het toegestane geheugengebied.

Waarom al dat gedoe met printf-formatting als het ook gewoon zo kan:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
std::ostream pFile3;
pFile3.open(str1.c_str());
pFile3 <<
    fname                               << "\n " <<
    patci.dimx                          << "\n " <<
    patci.dimy                          << "\n " <<
    patci.dimz                          << "\n " <<
    patci.xtable[0]-0.5*patci.psizex    << "\n " <<
    patci.ytable[0]-0.5*patci.psizey    << "\n " <<
    patci.ztable[0]-0.5*patci.psizez    << "\n " <<
    patci.psizex*patci.dimx             << "\n " <<
    patci.psizey*patci.dimy             << "\n " <<
    patci.psizez*patci.dimz             << "\n";

Dan zoekt de compiler voor jou de goede type-conversies uit.

  • MLM
  • Registratie: Juli 2004
  • Laatst online: 12-03-2023

MLM

aka Zolo

%f verwacht zover if weet float's, die ook 4 bytes zijn. Maar goed, C++ std::streams maken het wel moeilijker om dat soort fouten te maken, dus je hebt wel gelijk :)

-niks-


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 08:45

.oisyn

Moderator Devschuur®

Demotivational Speaker

sam.vimes schreef op dinsdag 15 april 2008 @ 13:42:
Ik denk dat de membervariabelen patci.psizex, patci.dimx, patci.psizey, patci.dimy, patci.psizez, patci.dimz van het type int zijn. (Dit is een veronderstelling, je geeft nl. niet voldoende info.)
Beter lezen ;)
MLM schreef op dinsdag 15 april 2008 @ 13:49:
%f verwacht zover if weet float's, die ook 4 bytes zijn.
%f verwacht doubles. Floats meegeven in de ellipsis werkt prima, omdat die gepromoveerd worden naar doubles (net als dat chars en shorts eerst gepromoveerd worden naar (unsigned) ints). Maar wel oppassen, want bij scanf verwacht ie dus wél pointer naar float.

[ Voor 5% gewijzigd door .oisyn op 15-04-2008 14:14 ]

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.


  • sam.vimes
  • Registratie: Januari 2007
  • Laatst online: 08-06 08:44
Je hebt gelijk. Ik zal de volgende keer mijn bril opzetten. B)
%f verwacht doubles. Floats meegeven in de ellipsis werkt prima, omdat die gepromoveerd worden naar doubles (net als dat chars en shorts eerst gepromoveerd worden naar (unsigned) ints).
Probleem hier is dat er geen floats worden doorgegeven, maar ints.
In dit geval is het probleem denk ik het snelst op te lossen door te casten naar double:
C++:
1
2
3
4
[...knip...]
(double)patci.psizex*patci.dimx,
(double)patci.psizey*patci.dimy,
(double)patci.psizez*patci.dimz); 
Maar wel oppassen, want bij scanf verwacht ie dus wél pointer naar float.
Dat is hier OT. :?

  • Stukfruit
  • Registratie: Oktober 2007
  • Niet online
Dat was idd ook mijn eerste gedachte toen ik de startpost las, maar heb het net even geprobeerd en hij geeft ze gewoon als floats (naar doubles) door en kan daarom geen reden zijn voor een over/onder/vastloper.

Dat zit wel Schnorr.


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 08:45

.oisyn

Moderator Devschuur®

Demotivational Speaker

sam.vimes schreef op dinsdag 15 april 2008 @ 15:37:
[...]

Je hebt gelijk. Ik zal de volgende keer mijn bril opzetten. B)

[...]

Probleem hier is dat er geen floats worden doorgegeven, maar ints.
In dit geval is het probleem denk ik het snelst op te lossen door te casten naar double:
C++:
1
2
3
4
[...knip...]
(double)patci.psizex*patci.dimx,
(double)patci.psizey*patci.dimy,
(double)patci.psizez*patci.dimz); 
En dat is dus niet waar, want zoals in de post die ik zojuist aanhaalde te lezen valt zijn psizex, psizex en psizez float. De operator*(float,int) levert ook een float op, wat vervolgens weer naar double gepromoveerd wordt omdat ze aan een variadic functie worden gegeven. Er gaat dus helemaal niets fout (afgezien van het std::string probleem wat al eerder is opgelost)
Dat is hier OT. :?
En mag ik daarom mijn opmerking niet nuanceren jegens MLM? :?

[ Voor 3% gewijzigd door .oisyn op 15-04-2008 16:02 ]

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.

Pagina: 1