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

[VC++] Vreemde crash in ntdll.dll

Pagina: 1
Acties:

  • Adion
  • Registratie: Januari 2001
  • Laatst online: 07:56
Ik heb een programma, gecompileerd met Visual C++ 2008 Express.
Op sommige computers crashed dit, maar op de meeste niet. De crashende pc's bleken tot nu toe allemaal WinXP SP2 te zijn, maar veel pc's met hetzelfde OS crashen niet.

Ik heb dus eens wat MessageBox() calls in mijn code gezet om uit te vissen waar het precies fout ging.
Dat bleek tussen de volgende 2 regels te zijn:
C++:
1
2
Imp = new RSFLOAT[Nwing];
ImpD = new RSFLOAT[Nwing];

(RSFLOAT is gewoon float op dit moment)
Erg vreemd dus dat de crash wel in de 2de maar niet in de eerste new gebeurde.
Het vervangen van new door malloc leverde niets op, maar vreemd genoeg lostte deze code de crash wel op:
C++:
1
2
Imp = (RSFLOAT *)malloc(sizeof(RSFLOAT) * Nwing * 2);
ImpD = &Imp[Nwing];

Opnieuw erg vreemd dus, dat een mallov van 2x de grootte wel lukt.

Helaas lijkt dit het probleem alleen te verplaatsen, want nu komt de crash iets verder in mijn programma voor, bij deze code:
C++:
1
2
std::ifstream mp3_file;
mp3_file.open(filename.c_str(), std::ios::in|std::ios::binary|std::ios::ate);


De crash ziet er zo uit:
Afbeeldingslocatie: http://img528.imageshack.us/img528/6961/problemzu7.jpg

Een tijdje geleden werkte het nog wel, maar niets aan de omliggende code is recent nog gewijzigd.
Heeft er dus iemand toevallig al eens hetzelfde voorgehad of enig idee wat ik nog kan proberen?

VirtualDJ 2024 - Fast Image Resizer - Instagram


  • Laurens-R
  • Registratie: December 2002
  • Laatst online: 29-12-2024
Heb je al regel voor regel gedebugged? Visual Studio heeft hiervoor "step" functionaliteit die erg handig is... Gewoon een breakpoint zetten voor de code waar de fout voorkomt en vervolgens met F10 en F11 (geloof ik) door de code heen "stappen".

Wat zegt de stacktrace verder?

Zoals je al aangeeft gebeurt het bij het creeren van het 2de object. Ik zou (indien mogelijk) de constructor van dat type eens doorlopen.

[ Voor 25% gewijzigd door Laurens-R op 12-03-2008 17:35 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 19-11 23:43

.oisyn

Moderator Devschuur®

Demotivational Speaker

Riekt naar heap corruption. Waarschijnlijk treedt een van de volgende scenario's op:

- Je schrijft buiten het bereik van een gealloceerde memory chunk
- Je schrijft naar een stuk geheugen wat je al hebt vrijgegeven
- Je gebruikt een ongeinitialiseerde pointer
- Je geeft een stuk geheugen meerdere keren vrij.

De laatste drie kun je makkelijk voorkomen door pointers altijd eerst op 0 te initialiseren, en weer op 0 te zetten nadat je ze vrijgeeft.

Maar om de bug nu te achterhalen kun je het volgende doen. Bouw een debug executable, en zet dit in je main:

C++:
1
2
3
4
5
6
7
8
#include <crtdbg.h>

int main()
{
    _CrtSetDbgFlag(_CRTDBG_CHECK_ALWAYS_DF);

    // ...
}


Dit zal je applicatie wel enorm vertragen, maar het helpt je wel de fout op te sporen - zodra je een assert krijgt in _CrtCheckMemory() dan weet je dat de fout zit tussen de huidige malloc/free/new/delete-aanroep en de vorige. Eventueel kun je dan in dat stuk code nog af en toe handmatig _CrtCheckMemory() aanroepen om exact te achterhalen wanneer de heap stuk gaat.

Een andere oplossing is gebruik maken van bepaalde tools zoals BoundsChecker of Rational Purify, die kunnen dat soort dingen detecteren en precies zeggen op welke regel code het fout gaat. Gratis tools voor Windows ken ik echter niet.

[ Voor 63% gewijzigd door .oisyn op 12-03-2008 17:56 ]

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.


  • Adion
  • Registratie: Januari 2001
  • Laatst online: 07:56
EvilB2k schreef op woensdag 12 maart 2008 @ 17:34:
Heb je al regel voor regel gedebugged? Visual Studio heeft hiervoor "step" functionaliteit die erg handig is... Gewoon een breakpoint zetten voor de code waar de fout voorkomt en vervolgens met F10 en F11 (geloof ik) door de code heen "stappen".

Wat zegt de stacktrace verder?

Zoals je al aangeeft gebeurt het bij het creeren van het 2de object. Ik zou (indien mogelijk) de constructor van dat type eens doorlopen.
Het type is float, en er wordt een array geinitializeerd, dus veel constructor is er niet aan.
Step by step debuggen kan helaas ook niet, want het probleem komt niet voor op m'n ontwikkel-pc. Idem voor stacktrace dus.
.oisyn schreef op woensdag 12 maart 2008 @ 17:45:
Riekt naar heap corruption. Waarschijnlijk treedt een van de volgende scenario's op:

- Je schrijft buiten het bereik van een gealloceerde memory chunk
- Je schrijft naar een stuk geheugen wat je al hebt vrijgegeven
- Je gebruikt een ongeinitialiseerde pointer
- Je geeft een stuk geheugen meerdere keren vrij.

De laatste drie kun je makkelijk voorkomen door pointers altijd eerst op 0 te initialiseren, en weer op 0 te zetten nadat je ze vrijgeeft.
Dat is inderdaad iets dat ik eigenlijk al altijd doe.
Maar om de bug nu te achterhalen kun je het volgende doen. Bouw een debug executable, en zet dit in je main:

C++:
1
2
3
4
5
6
7
8
#include <crtdbg.h>

int main()
{
    _CrtSetDbgFlag(_CRTDBG_CHECK_ALWAYS_DF);

    // ...
}


Dit zal je applicatie wel enorm vertragen, maar het helpt je wel de fout op te sporen - zodra je een assert krijgt in _CrtCheckMemory() dan weet je dat de fout zit tussen de huidige malloc/free/new/delete-aanroep en de vorige. Eventueel kun je dan in dat stuk code nog af en toe handmatig _CrtCheckMemory() aanroepen om exact te achterhalen wanneer de heap stuk gaat.
Bedankt, dat wist ik niet. Ik ga het meteen eens proberen!

VirtualDJ 2024 - Fast Image Resizer - Instagram


  • Adion
  • Registratie: Januari 2001
  • Laatst online: 07:56
Mh, _CrtCheckMemory() werkt enkel in een debug build (wel logisch natuurlijk)
Alleen kan ik de debug versie blijkbaar niet uitvoeren op de machine waar het probleem zich voor doet. (waarschijnlijk omdat de debug runtimes daar niet geinstalleerd zijn)
Het programma is overigens Visual Basic 6 die gebruik maakt van een dll in C++, en indien ik de debug versie van de dll gebruik krijg ik een crash in msvbvm60.dll.

De debug versie crashed overigens nog steeds niet op de ontwikkelmachine, zelfs met die _CrtSetdbgFlag. Ik zou verwachten dat het heap probleem zich dan overal zou voor doen waar dezelfde code wordt uitgevoerd?

VirtualDJ 2024 - Fast Image Resizer - Instagram


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 19-11 23:43

.oisyn

Moderator Devschuur®

Demotivational Speaker

Adion schreef op woensdag 12 maart 2008 @ 18:51:
Mh, _CrtCheckMemory() werkt enkel in een debug build (wel logisch natuurlijk)
Alleen kan ik de debug versie blijkbaar niet uitvoeren op de machine waar het probleem zich voor doet. (waarschijnlijk omdat de debug runtimes daar niet geinstalleerd zijn)
Dan moet je met de static runtime linken ipv de dynamic runtime.

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.


  • biomass
  • Registratie: Augustus 2004
  • Laatst online: 00:23
Adion schreef op woensdag 12 maart 2008 @ 18:51:
De debug versie crashed overigens nog steeds niet op de ontwikkelmachine, zelfs met die _CrtSetdbgFlag. Ik zou verwachten dat het heap probleem zich dan overal zou voor doen waar dezelfde code wordt uitgevoerd?
Dat is ook een symptoom van heap corruption, in de debug versie is er 'niks' aan de hand, totdat je de release versie gaat draaien. .oisyn zegt het niet letterlijk; check ook je statisch gealloceerd geheugen (compile-time buffers) eens. D'r kunnen hele rare dingen gebeuren als je daar een buffer overflow in veroorzaakt.

  • Adion
  • Registratie: Januari 2001
  • Laatst online: 07:56
Ok, door statisch te linken is het inderdaad gelukt om de debug versie op de probleem-machine te draaien.
Helaas zoals biomass zegt werkt de debug versie zonder fouten, en blijkbaar hebben de _CrtCheckMemory() dus ook geen fouten ontdekt? (Ik heb _CrtCheckMemory() dus nergens expliciet opgeroepen momenteel, maar door _CrtSetdbgFlag hoort de applicatie dan toch ook te stoppen van zodra een fout ontdekt is?)

Overigens snap ik nog niet goed wat er dan precies fout gaat bij de allocatie.
malloc hoort toch op zoek te gaan naar een nieuw stuk geheugen? Dat er in een leeg stuk geheugen toch al geschreven zou zijn hoort toch op dat moment nog geen fouten te veroorzaken, maar pas als dat stuk geheugen opnieuw ingelezen word?
Ook snap ik nog niet helemaal waarom het dan enkel op bepaalde systemen consequent fout gaat en op andere nooit.

VirtualDJ 2024 - Fast Image Resizer - Instagram


  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

Ik let misschien even niet goed op, maar ben je zeker dat je geen stack overflow hebt?

ASSUME makes an ASS out of U and ME


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 19-11 23:43

.oisyn

Moderator Devschuur®

Demotivational Speaker

Adion schreef op woensdag 12 maart 2008 @ 20:54:
Ok, door statisch te linken is het inderdaad gelukt om de debug versie op de probleem-machine te draaien.
Helaas zoals biomass zegt werkt de debug versie zonder fouten, en blijkbaar hebben de _CrtCheckMemory() dus ook geen fouten ontdekt? (Ik heb _CrtCheckMemory() dus nergens expliciet opgeroepen momenteel, maar door _CrtSetdbgFlag hoort de applicatie dan toch ook te stoppen van zodra een fout ontdekt is?)
Waarschijnlijk uninitialized variabelen. Dat is in debug builds anders dan in release builds.
Overigens snap ik nog niet goed wat er dan precies fout gaat bij de allocatie.
malloc hoort toch op zoek te gaan naar een nieuw stuk geheugen? Dat er in een leeg stuk geheugen toch al geschreven zou zijn hoort toch op dat moment nog geen fouten te veroorzaken, maar pas als dat stuk geheugen opnieuw ingelezen word?
Als je een stuk geheugen alloceert, dan staat om dat stuk gealloceerde geheugen meestal nog informatie over dat geheugen, zoals pointers naar een volgend en een vorig geheugen blok. Als je hier overheen gaat schrijven, dan kunnen malloc() en consorten hun werk niet meer goed doen, en dat kan resulteren in een crash (als je mazzel hebt - als je pech hebt gebeurt er niets, maar krijg je de fout spontaan bij iemand anders, wat nu dus bij jou het geval is)
H!GHGuY schreef op woensdag 12 maart 2008 @ 21:02:
Ik let misschien even niet goed op, maar ben je zeker dat je geen stack overflow hebt?
Dan hoor je een dergelijke exception te krijgen.

[ Voor 8% gewijzigd door .oisyn op 12-03-2008 21:41 ]

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.


  • Adion
  • Registratie: Januari 2001
  • Laatst online: 07:56
Ok, bedankt voor de verduidelijking.
Is het ook mogelijk dat code die niet wordt uigevoerd invloed heeft op deze fout?
Het zit namelijk zo: Om muziekbestanden te decoderen heb ik een deel code voor een aantal bestandsformaten van mezelf, maar heb ik ook de mogelijkheid tot het gebruik van 2 libraries (FMod en Bass)
Om te kiezen welke van deze 2 libraries gebruikt worden heb ik 2 Preprocessor definities USEFMOD en USEBASS.
Nu viel me net op dat alleen de build met USEFMOD crasht, maar niet die met USEBASS.
Ik heb dan heel de code doorzocht om nog eens na te gaan waar ik USEBASS of USEFMOD gebruikt had, en het vreemde is dus dat de crash ook voorkomt als de code binnen deze #ifdef's niet uitgevoerd word.
Om dit zeker te testen heb ik eerst overal breakpoints gezet en de code in debug eens gedraaid, en inderdaad, nergens werd deze code tot het moment van de crash uitgevoerd.
Het verwijderen van beide preprocessor definitions zorgde ervoor dat er nu geen crash meer voorkomt.
Uiteraard is dit niet helemaal een oplossing vermits er nu een aantal functies niet meer zullen werken.

VirtualDJ 2024 - Fast Image Resizer - Instagram


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 16-11 18:33
Het "leuke" van dit soort bugs ( Heisenbug ) is dat ze door veranderingen in de code kunnen verplaatsen.

Stel dat door het weglaten van een define de adressen van variabelen op je stack, of in je static store verandert, dan kan het zijn dat je bug dus plotseling over een andere variabele heenschrijft en de bug een heel ander gedrag gaat vertonen.

Ik heb het een keer gehad met een buffer overflow bug die over de logfile variabele schreef. Het zet je compleet op het verkeerde been omdat je gaat zoeken in je logfile code wat daar fout zit, terwijl de bug heel ergens anders zit.

Het kunnen echte showvertragers zijn wat dat betreft. :)

NB om je vraag te beantwoorden: Ja, het is mogelijk dat code die niet wordt uitgevoerd invloed heeft op je bug. :P

[ Voor 8% gewijzigd door farlane op 13-03-2008 10:38 ]

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.

Pagina: 1