[C++.NET2005] BadImageFormatException tijdens aanroep method

Pagina: 1
Acties:

  • RobLemmens
  • Registratie: Juni 2003
  • Laatst online: 12-04 17:37
Wat ik nu weer aan men fiets heb hangen.. Ik krijg constant op een bepaald stuk code de exceptie BadImageFormatException. Wat zoeken naar de mogelijke oorzaak verteld mij dat je deze exceptie krijgt op het moment dat je een assembly probeert in te laden als managed clr terwijl deze dat niet is. Probleem is echter dat ik geen code uit een andere assembly gebruik op dat punt. Verder gezoek op google verteld me dat er dit voorkomt bij het laden van een assembly die niet de juiste versie van de runtime support. Ik zit in dezelfde assembly dus dit lijkt me niet van toepassing. Verder vindt ik helemaal niets dat me kan helpen.
Dit is wat ik doe: Ik roep een method in een bepaald object voor de eerste keer aan (de rest van het programma loopt al een tijdje) en gelijk krijg ik deze exceptie, men uiteindelijke vermoeden is dat de jit over zen nek gaat en deze exceptie naar buiten knalt. Toen ben ik maar eens wat code gaan uitdocumenteren om zo het stuk code te vinden dat ervoor zorgt dat het fout loopt.

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
  bool Document::ExportFields(Command^ pCmd, bool bIncludePageData)
  {
   if(pCmd == nullptr) return false; 
 
   pCmd->AddField(VortexCommandField::DOCNR,iDocNr); 

   /* database fields */ 
   if(!LoadDBFields()) return false; 
   pCmd->AddField(VortexCommandField::ARCHIVELOCATION, iArchiveLocation); 
   pCmd->AddField(VortexCommandField::OWNER,           iOwner); 
   pCmd->AddField(VortexCommandField::SENDER,          iSender); 
   pCmd->AddField(VortexCommandField::DOCTYPE,         iDocType); 
   pCmd->AddField(VortexCommandField::DESCRIPTION,     sDescription); 
   pCmd->AddField(VortexCommandField::UPDATEBY,        iUpdateBy); 
   pCmd->AddField(VortexCommandField::DOCDATE,         dtDocDate); 
   pCmd->AddField(VortexCommandField::RECDATE,         dtRecDate); 
   pCmd->AddField(VortexCommandField::DONEDATE,        dtDoneDate); 
   pCmd->AddField(VortexCommandField::UPDATED,         dtUpdate); 
   pCmd->AddField(VortexCommandField::CREATED,         dtCreated); 

   
   /* page information */ 
   if(LoadPageList() && (aPage->Count > 0))
   {
    Text::StringBuilder^sb = gcnew Text::StringBuilder(aPage->Count * 7); 
    Monitor::Enter(aPage); 
    try
    {  
     for each(Generic::KeyValuePair<int,Page^>^ kvp in aPage)
     { 
      sb->Append(kvp->Key.ToString()); 
      sb->Append(","); 
      sb->Append(kvp->Value->FileNr.ToString());
      sb->Append(";"); 
     } 
     pCmd->AddField(VortexCommandField::PAGELIST, (sb->Length == 0) ? "" : sb->ToString()); 
    }
    finally
    {
     Monitor::Exit(aPage); 
    }
   }
   else
   {
    pCmd->AddField(VortexCommandField::PAGELIST,""); 
   }     

   /* Page data*/ 
   if(bIncludePageData)
   { 
    LoadPages(); 
    /* voor elke pagina in dit document */ 
    for each(Generic::KeyValuePair<int,Page^>^ kvp in aPage) 
    { 
     /* maak een reply met page-data */    
     Command^ pCmdRep    = gcnew Command(); 
     pCmdRep->CommandId  = VortexCommand::GET_PAGE_INFO; 
     pCmdRep->Type       = VortexCommandType::REPLY; 
     /* export page fields & data */ 
     kvp->Value->ExportFields(pCmdRep); 
     /* voeg toe aan het basis command */ 
     pCmd->AddChildCommand(pCmdRep); 
    } 
   }   
               
   return true; 
  }



Als ik dit stuk uitdocumenteer dan werkt het gewoon:

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
  /* page information */ 
   if(LoadPageList() && (aPage->Count > 0))
   {
    Text::StringBuilder^sb = gcnew Text::StringBuilder(aPage->Count * 7); 
    Monitor::Enter(aPage); 
    try
    {  
     for each(Generic::KeyValuePair<int,Page^>^ kvp in aPage)
     { 
      sb->Append(kvp->Key.ToString()); 
      sb->Append(","); 
      sb->Append(kvp->Value->FileNr.ToString());
      sb->Append(";"); 
     } 
     pCmd->AddField(VortexCommandField::PAGELIST, (sb->Length == 0) ? "" : sb->ToString()); 
    }
    finally
    {
     Monitor::Exit(aPage); 
    }
   }
   else
   {
    pCmd->AddField(VortexCommandField::PAGELIST,""); 
   }     


De method LoadPageList() is het niet, die word ergens anders vrolijk gebruikt. Ook al het ander spul word overal door het programma heen zonder enig probleem gebruikt. Het lijkt gewoon allemaal goed, ook tijdens compilatie krijg ik geen enkele error of warning. De debugger knalt gewoon eruit met de exceptie op het moment van aanroepen van de method. (neem aan dat ie dan gejit wordt).

Iemand enig idee wat de oorzaak van BadImageFormatException in deze method kan zijn? Ben ten einde raad.

  • RobLemmens
  • Registratie: Juni 2003
  • Laatst online: 12-04 17:37
Dan lees je je eigen post en denkt... |:(

Waarom heb ik dit niet effe geprobeerd:


C++:
1
  sb->Append(kvp->Key.ToString()); 
"

veranderen in:

C++:
1
2
  int iKey = kvp->Key;
  sb->Append(iKey.ToString()); 



Nu werkt het gewoon. Is dit een bug in de compiler? ( tis een beta )

kvp is van type KeyValuePair<int,Page^>, key is dan toch een int?

Zou ik dit moeten melden of is het logisch dat dit fout gaat?

[ Voor 21% gewijzigd door RobLemmens op 18-08-2005 12:14 ]


  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Ik zie niet in wat er verkeerd aan je andere code moet zijn waardoor je een BadImageFormatException moet krijgen.

In princiepe doe je precies hetzelfde alleen met een tussenstap om de key in een int var te zetten. Aangezien je key idd van het type Int zou moeten zijn zou het goed moeten gaan. Als het type niet goed zou zijn zou je al een compiler error moeten krijgen lijkt me.

Kan je de exception ook krijgen als je het in een klein test programmatje doet?

“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.”


  • RobLemmens
  • Registratie: Juni 2003
  • Laatst online: 12-04 17:37
rwb schreef op donderdag 18 augustus 2005 @ 12:16:
Kan je de exception ook krijgen als je het in een klein test programmatje doet?
Ik ga dat eens proberen, laat hier wel wat weten.

  • RobLemmens
  • Registratie: Juni 2003
  • Laatst online: 12-04 17:37
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
#pragma managed

using namespace System;
using namespace System::Collections::Generic; 

public ref class TestObject
{
 public: 
  TestObject() {}; 
  ~TestObject() {}; 
};          
  
void main()
{
 Dictionary<int,TestObject^>^ aDict       = gcnew Dictionary<int,TestObject^>(); 
 array<TestObject^>^          aTestObject = gcnew array<TestObject^>(10);

 for(int i = 0; i < 10; i++) aDict->Add(i,aTestObject[i]);  
   
 for each(KeyValuePair<int,TestObject^>^ kvp in aDict)
 {
  Console::WriteLine(String::Format("Key = {1}",kvp->Key.ToString())); 
 }

 Console::ReadLine(); 
}


En ook hier, BadImageFormatException vanuit "crtexe.c"

C++:
1
2
3
4
5
6
7
#ifdef WPRFLAG
            __winitenv = envp;
            mainret = wmain(argc, argv, envp);
#else  /* WPRFLAG */
            __initenv = envp;
            mainret = main(argc, argv, envp);      <<<<   Hier knalt ie eruit.
#endif  /* WPRFLAG */



Is dit een bug in de compiler? Moet ik dit melden aan microsoft?

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Ik weet niet zoveel van c++.net ( 2005 ) maar ik ga er hier even van uit dat ^ gebruikt wordt om een soortement van managed pointer aan te geven en dat gcnew gewoon de .net variant is van de new operator.

Dan zie ik in je code niet zo snel iets verkeerds en al helemaal niet waarom je een BadImageFormatException krijgt.

moet je trouwens bij
C++:
1
gcnew array<TestObject^>(10);


geen [ en ] gebruiken in plaats van ( en )? maarja dat lijkt me iets waar de compiler anders wel over zou vallen.

Ik zou ieder geval even een mailtje naar microsoft sturen. Als het een bug is kunnen ze er mischien wat mee en als het geen bug is sturen ze je mischien de reden wel.

[ Voor 15% gewijzigd door Woy op 18-08-2005 13:04 ]

“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.”


  • RobLemmens
  • Registratie: Juni 2003
  • Laatst online: 12-04 17:37
rwb schreef op donderdag 18 augustus 2005 @ 13:03:

moet je trouwens bij
C++:
1
gcnew array<TestObject^>(10);


geen [ en ] gebruiken in plaats van ( en )? maarja dat lijkt me iets waar de compiler anders wel over zou vallen.

Ik zou ieder geval even een mailtje naar microsoft sturen. Als het een bug is kunnen ze er mischien wat mee en als het geen bug is sturen ze je mischien de reden wel.
Met gcnew alloceer je een object op de managed heap, elk ding daar is van type System::Object en wordt geinitialiseerd met een constructor, vandaar de ().

Ga het melden, laat de uitkomst terzijnet tijd wel hier achter.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 01-05 21:33

.oisyn

Moderator Devschuur®

Demotivational Speaker

Heb even wat geprobeerd, het lijkt erop dat hij moeilijk heeft met het type als generic type. Een int in een value class waar je ToString() op aanroept gaat prima, maar bij een generic value class waarbij die int een generic type is gaat het fout.

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
using namespace System; 

generic <class T>
value class Test
{
public:
    T value;
};

int main() 
{
    Test<int> t;
    Console::WriteLine(t.value.ToString());
}


.edit: hetzelfde verhaal bij ref classes overigens.

offtopic:
Ik zie trouwens dat ik m'n syntax highlighter eens moet updaten om C++/CLI te ondersteunen ;)

[ Voor 17% gewijzigd door .oisyn op 18-08-2005 13:23 ]

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.


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 01-05 21:33

.oisyn

Moderator Devschuur®

Demotivational Speaker

rwb schreef op donderdag 18 augustus 2005 @ 13:03:
moet je trouwens bij
C++:
1
gcnew array<TestObject^>(10);


geen [ en ] gebruiken in plaats van ( en )? maarja dat lijkt me iets waar de compiler anders wel over zou vallen.
[nohtml]
Nee, in C# en Java heb je een int[] gewoon als array type, maar in C++ is dat gewoon een native int array. Ze hebben een tempate class in het leven geroepen (zo ziet het eruit iig, het zal wel een intrinsic zijn en niet daadwerkelijk een user-defined class) om managed arrays te maken. Een array is dan ook gewoon een object als elke andere, en de lengte van de array geef je mee als parameter van de constructor van het object.

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.


  • RobLemmens
  • Registratie: Juni 2003
  • Laatst online: 12-04 17:37
Blijkbaar is deze bug ooit gereport geworden voor de eerste beta, zou gefixed moeten zijn in beta2.

http://lab.msdn.microsoft...8c-471f-8ff4-e0103a0b6688

Heb hem nog maar eens gesubmit.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 01-05 21:33

.oisyn

Moderator Devschuur®

Demotivational Speaker

Het gaat overigens ook alleen maar fout bij native types. Als je een eigen value class gebruikt of zelfs iets als een System::Decimal dat geen native type kent in C++/CLI dan gaat het wel goed.

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.


  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
.oisyn schreef op donderdag 18 augustus 2005 @ 13:21:
[...]

[nohtml]
Nee, in C# en Java heb je een int[] gewoon als array type, maar in C++ is dat gewoon een native int array. Ze hebben een tempate class in het leven geroepen (zo ziet het eruit iig, het zal wel een intrinsic zijn en niet daadwerkelijk een user-defined class) om managed arrays te maken. Een array<int> is dan ook gewoon een object als elke andere, en de lengte van de array geef je mee als parameter van de constructor van het object.
Ok logisch idd.
was even in de war omdat je in c en c++ idd gewoon
C++:
1
int myIntArray[ 10 ];

kan doen.

“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.”

Pagina: 1