Toon posts:

[C++] Memory corruption

Pagina: 1
Acties:

Verwijderd

Topicstarter
Okee, na de vorige topics wederom een probleem. Iedere keer heb ik het idee dat het probleem is opgelost en komt daarna zonder grote wijzigingen wederom terug. Het wijst allemaal naar memory corruption maar het ik kan er met geen mogelijkheid achter komen. Het probleem doet zich niet altijd voor en de locatie (step by step) waar het gebeurt varieért ook iedere keer. Geen goede condities om te debuggen ;).

Purity en Boundschecker vinden geen enkele problemen. Ook dit helpt niet echt. Ik had stille hoop dat een van deze twee applicaties wel enige problemen zou vinden.

Het huidige probleem is dat de waarde van een classvariabele spontaan veranderd. Het gaat hierbij om een windows socket handle. De waarde veranderd spontaan van vijfduizend-nogwat naar 0. (Dit geeft mij het idee dat het door een memset instructie komt. Ook al wordt er geen memset instructie uitgevoerd ;))

Hier een code fragment waar de socket handle spontaan veranderd:

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
class ClassA
{
private:
  int m_var;
  string m_var2;

public:
  void resetContents(void);
};

void ClassA::resetContents(void)
{
   this->m_var = 0;
   this->m_var2 = "";
}

// 
// Hier klopt de watch van de socket handle nog
//
Class A;
A.resetContents();

//
// Hier klopt de watch waarde niet meer
//


Ik heb werkelijk geen idee meer hoe ik dit probleem op zou moeten kunnen lossen :P. Dit heb ik eerder gehoord >:). Hoe kom ik er achter (met VS2005) waar de waarde wordt veranderd en waarom deze wordt veranderd.

Een hulpeloze tweaker :P.

Verwijderd

VS2005 heeft een uitstekende debugger toch?

Lijkt me een kwestie van een watch toevoegen en de boel draaien?

En natuurlijk IDA Pro... als je er daarmee niet uit komt dan is het onvindbaar :+

[ Voor 27% gewijzigd door Verwijderd op 27-03-2007 13:36 ]


Verwijderd

Topicstarter
Verwijderd schreef op dinsdag 27 maart 2007 @ 13:35:
VS2005 heeft een uitstekende debugger toch?

Lijkt me een kwestie van een watch toevoegen en de boel draaien?

En natuurlijk IDA Pro... als je er daarmee niet uit komt dan is het onvindbaar :+
Hierbij een quote uit mijn TS:
Het probleem doet zich niet altijd voor en de locatie (step by step) waar het gebeurt varieért ook iedere keer. Geen goede condities om te debuggen ;).

Purity en Boundschecker vinden geen enkele problemen. Ook dit helpt niet echt. Ik had stille hoop dat een van deze twee applicaties wel enige problemen zou vinden.
Ik zal eens naar IDA Pro gaan zoeken. Geen idee wat ik me daarbij voor moet stellen :D.

[ Voor 6% gewijzigd door Verwijderd op 27-03-2007 13:37 ]


Verwijderd

Ja maar het voordeel van een watch is dat ie aangeeft precies waar ie mee bezig is op het moment dat het misgaat.

Op die manier kun je soms een probleem wel vinden met een watch terwijl het niet te vinden is met een step-by-step (bijvoorbeeld wanneer er tijdsgebonden factoren meespelen die natuurlijk verstoord worden bij het debuggen).

IDA Pro is een geweldig programma, een van de beste debuggers die ik ooit heb gezien en het kan zoveel meer tov de standaard debugger.

Vooral de interface en grafische weergave van de patronen tijdens de uitvoer van een programma zijn geweldig handig.

Dit soort dingen:

Afbeeldingslocatie: http://www.hexblog.com/ida_pro/pix/simplex_04_new_blocks.gif

http://www.datarescue.com/idabase/5preview/index.htm

[ Voor 37% gewijzigd door Verwijderd op 27-03-2007 13:41 ]


Verwijderd

Topicstarter
Okee, ik heb een watch staan op de variable. Echter krijg ik geen melding wanneer er iets veranderd (wat ik nog al vreemd vind en wel verwacht had). Ik kan de waarde wel volgen door er stap voor stap doorheen te lopen. Het is idd logisch dat er dan tijdsafhankelijke zaken veranderen waardoor de bug niet te traceren.

Heb jij het over dezelfde VS2005 watches als ik? :P. Zoals gezegd krijg ik geen melding wanneer de waarde van de variabele veranderd. Of doe ik iets verkeerd? :P.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 10:04

.oisyn

Moderator Devschuur®

Demotivational Speaker

Je moet een data breakpoint plaatsen. Eerst moet je het adres van de handle weten, plaats dus een code breakpoint op het moment dat je vanuit de debugger bij die handle variabele kunt. Vraag het adres op, en doe dan Debug -> New Breakpoint, tabblad Data, en voer het (hexadecimale) adres in het variabele veld. Haal context leeg als daar iets in staat. Ga nu verder met runnen, en de debugger stopt je app elke keer als dat adres wordt overschreven.

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.


Verwijderd

Inderdaad wat .oisyn zegt. Blijkbaar heeft de VS2005 debugger geen break mogelijkheid bij een watch...

Verwijderd

Topicstarter
.oisyn schreef op dinsdag 27 maart 2007 @ 13:48:
Je moet een data breakpoint plaatsen. Eerst moet je het adres van de handle weten, plaats dus een code breakpoint op het moment dat je vanuit de debugger bij die handle variabele kunt. Vraag het adres op, en doe dan Debug -> New Breakpoint, tabblad Data, en voer het (hexadecimale) adres in het variabele veld. Haal context leeg als daar iets in staat. Ga nu verder met runnen, en de debugger stopt je app elke keer als dat adres wordt overschreven.
Volgende probleem, hoe krijg ik het adres van een classvariabele van het type SOCKET te pakken? :D.
Stukje voorbeelcode:

C++:
1
2
3
4
5
6
7
8
class A
{
private
  SOCKET m_handle;

public:
  //blaat
};


Hoe krijg ik het adres van de m_handle variabele. In de debugger is immers alleen de waarde te zien en niet het fysieke adres. Het fysieke adres van de class instantie is uiteraard wel bekend. kan ik hier iets mee?

Edit:
Ben er al uit denk ik :P. Lang leve het immediate venster ;)

[ Voor 3% gewijzigd door Verwijderd op 27-03-2007 14:14 ]


Verwijderd

Topicstarter
Nu mag ik een boon worden. Ik krijg nu idd braaf een messagebox wanneer er ook maar een regel code de desbetreffende classvariabele aanraakt.

Voordat ik de methode in ga klopt de waarde en wanneer ik de methode verlaat klopt de waarde van de classvariabele niet meer. Het betreft hier een drietal simpele assigns in een constructor. Gedurende deze methode krijg ik geen enkel data breakpoint (welke voorheen prima werken).

Ik heb nu dus werkelijk waar geen idee meer hoe ik verder zou moeten zoeken naar de oorzaak. Het probleem verdwijnt spontaan wanneer ik het probleem op het spoor ben :P.

Iemand nog suggesties? Hoe zou ik met IDA Pro te werk moeten gaan om dit probleem te vinden? Ik ben niet bekend met IDA Pro namelijk :P.

[ Voor 1% gewijzigd door Verwijderd op 27-03-2007 14:59 . Reden: typefoutje :P ]


Verwijderd

Kun je eens proberen die assigns weg te commenten en kijken of dat het probleem oplost (waarschijnlijk niet).

Met IDA Pro werken is niet echt heel simpel uit te leggen, er zijn hele boeken over geschreven en de manual is ook een pittige.

Maar als je bekend bent met debuggers dan moet je er met IDA zeker uit kunnen komen, alles spreekt redelijk voor zich.

Hoe ik het zou doen in IDA:

Watch plaatsen op de juiste variabele, aangeven te breaken wanneer deze variabele gewijzigd wordt en eventueel de conditie daarbij dat de variabele 0 wordt (want dat was het geval toch)?

Dan het breakpoint verleggen naar een van de hogere functies van de functie waarin het mis ging, dan vervolgens die functie heel voorzichtig stap voor stap doorlopen en kijken welke aanroep er gedaan wordt waardoor er uberhaupt iets kan gebeuren met de variabele.

Met IDA kun je tot op machinetaal niveau, dus als het daarmee niet te vinden is...

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 10:04

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op dinsdag 27 maart 2007 @ 14:58:
Nu mag ik een boon worden. Ik krijg nu idd braaf een messagebox wanneer er ook maar een regel code de desbetreffende classvariabele aanraakt.

Voordat ik de methode in ga klopt de waarde en wanneer ik de methode verlaat klopt de waarde van de classvariabele niet meer. Het betreft hier een drietal simpele assigns in een constructor. Gedurende deze methode krijg ik geen enkel data breakpoint (welke voorheen prima werken).
Weet je zeker dat je naar de goede variabele kijkt? Het adres van een variabele in je watchwindow kun je natuurlijk gewoon opvragen door &variabele te doen :)

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.


Verwijderd

Topicstarter
Hier een quote uit mijn immediate window voordat het probleem zich voordoet:
&m_hSocket
0x01b5af54
Ik heb met de memory viewing tool bekeken of de waarde idd op dat adres staat en dat is idd het geval.

En nu een quote op het moment dat de variabele van waarde veranderd is:
&m_hSocket
0x01b59c2c
Hoe kan het dat het adres van mijn classmember (en dus waarschijnlijk mijn klasse) zo ineens van lokatie veranderd? :P. Verklaard wel waarom ik geen breakpoint krijg ;)

Iemand ideeën? Het betreft gewoon een klasse gealloceerd met de standaard operator new.

[ Voor 9% gewijzigd door Verwijderd op 27-03-2007 16:19 ]


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 30-11 00:17
Verwijderd schreef op dinsdag 27 maart 2007 @ 16:13:
Hoe kan het dat het adres van mijn classmember (en dus waarschijnlijk mijn klasse) zo ineens van lokatie veranderd? :P. Verklaard wel waarom ik geen breakpoint krijg ;)
Tussendoor een keer opnieuw gealloceerd door een copy oid?

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.


Verwijderd

Je kunt toch ook op dezelfde manier bekijken wanneer de pointer gewijzigd wordt? Dan weet je precies waar het gebeurt lijkt me.

Wel een beetje wazig hoor, maar vaak blijken dit hele kleine simpele probleempjes te zijn die je niet nog eens zullen overkomen. Dat is in ieder geval mijn ervaring.

Verwijderd

Topicstarter
farlane schreef op dinsdag 27 maart 2007 @ 17:50:
[...]

Tussendoor een keer opnieuw gealloceerd door een copy oid?
Nee, jammergenoeg is dat het niet :P.
Verwijderd schreef op woensdag 28 maart 2007 @ 07:54:
Je kunt toch ook op dezelfde manier bekijken wanneer de pointer gewijzigd wordt? Dan weet je precies waar het gebeurt lijkt me.

Wel een beetje wazig hoor, maar vaak blijken dit hele kleine simpele probleempjes te zijn die je niet nog eens zullen overkomen. Dat is in ieder geval mijn ervaring.
Het idiote is dat een data breakpoint op de pointer geen resultaten geeft.

Laten we iig hopen dat dit 'simpele probleempje' idd iets is wat ik in de directe toekomst niet weer tegenkom :P.

Iemand nog andere ideeën? Al zijn ze nog zo gek, alle ideeën en suggesties zijn momenteel welkom :P.

Edit:
Ik heb het probleem momenteel weten terug te traceren naar:

C++:
1
2
char *packetBuffer = (char*)malloc(_SEND_BUFFER_SIZE);
memset(packetBuffer, 0, _SEND_BUFFER_SIZE);


_SEND_BUFFER_SIZE is gedefinieerd als 65536

Voor zover ik kan zien zou dit niet fout mogen gaan. De memset instructie
overschrijft echter wel gegevens die ik graag wil bewaren (zoals de socket handel waarover ik spraak in de TS :P)

Nu zit ik nog met het probleem dat ik uit moet vissen waardoor malloc mijn eerder gealloceerde klasses overschrijft. Hrmm... waarom vinden Purify, BoundsChecker en Memory Validator hier niets over? Ik heb deze alle 3 reeds met de meest nauwkeurige instellingen gedraait. Dan zou ik toch verwachten dat er een melding zou komen bij een eventuele heap corruption.

Daarnaast hangt de code vol met _CrtCheckMemory assertions. Ook deze pikken helemaal niets op. Iemand nog ideeën over hoe ik achter de oorzaak van dit probleem kan komen? :/.

[ Voor 34% gewijzigd door Verwijderd op 28-03-2007 10:34 ]


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 30-11 00:17
malloc? Je gebruikt toch C++? Wordt ie soms door delete weer vrijgegeven oid?

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.


Verwijderd

Topicstarter
Nopez, hij wordt braaf weer vrijgegeven door free :D. Zoals het hoort :).

En ja, het is idd C++ op dit kleine stukje code na :P.

Edit:
Ik zit dermate met mijn handen in mijn haar dat ik alles aan het proberen ben :P.

Edit 2:
Het probleem lijkt idd te zijn dat de pointer naar mijn klasse veranderd. Al kan ik er nog niet achter komen waarom dit gebeurt :/.

[ Voor 51% gewijzigd door Verwijderd op 28-03-2007 11:23 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 10:04

.oisyn

Moderator Devschuur®

Demotivational Speaker

Data breakpoint op de pointer zetten? Natuurlijk even opletten dat je niet de breakpoint zet op het adres waar de pointer naar wijst, maar juist het adres van de pointer zelf :)

En dat malloc+memset je gegevens overschrijft wijst er vrijwel zeker op dat je instance is gedelete waardoor het geheugen weer vrijkomt en voor die allocatie wordt gebruikt.

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.


Verwijderd

Topicstarter
Hrmm... ik ga het nog vager maken dan dat het al is :P.

Ik heb zonet een data breakpoint geplaatst op de pointer naar de klasse. Deze pointer veranderd niet van waarde. Toen kwam ik op het idee om binnen verschillende methodes de waarde van this eens te bekijken.

Het gaat om een Socket klasse. Daarnaast is er een ThreadConnection klasse welke gebaseerd is op de Socket klasse. De socket klasse bevat Send methodes om data te versturen.

De code ziet er als volgt uit:

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
class Socket 
{
private:
  SOCKET m_hSocket;

public:
  void Send(...)
  {
     // Wanneer ik hier via een breakpoint this invoer in het immediate window dan
     // krijg ik alleen maar rotzooi te zien. Het is dus logisch dat m_hSocket ook een
     // vreemde waarde bevat.
  }
}

class ThreadConnection
{
public:
  void methode(void)
  {
    // Hier bevat this nog een waarde waarmee de juiste m_hSocket wordt gevonden.

    // Aanroep naar onze baseclass Send methode.
    // Binnen deze methode heeft de this pointer een compleet andere waarde
    // dan binnen deze methode en lijkt het me logisch dat m_hSocket dus ook een andere waarde heeft.
    Send(...);
  } 
}


Het lijkt er dus op dat bij de overgang van ThreadConnection naar baseclass Socket de this pointer de vernieling in wordt geholpen. Hrmm... iemand een verklaring waarom dit gebeurt? :/

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 10:04

.oisyn

Moderator Devschuur®

Demotivational Speaker

Schrijf je toevallig buiten de bounds van een lokale array in ThreadConnection::methode(), of in een van de functies die vandaaruit aangeroepen wordt?

[ Voor 27% gewijzigd door .oisyn op 28-03-2007 14:38 ]

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.


Verwijderd

Topicstarter
Er komen geen lokale arrays voor binnen de desbetreffende methode. Verder is de this pointer al om zeep geholpen nog voordat de eerste regel in de methode is uitgevoerd :/.

Edit:
Okee, ik sta op het punt om me gewonnen te geven :P. Wie geeft de winnende tip? :D.

[ Voor 22% gewijzigd door Verwijderd op 28-03-2007 16:13 ]

Pagina: 1