Vra

So, ek het hulp nodig.Ek werk op'n projek in C++.Egter, ek dink ek het een of ander manier daarin geslaag om korrupte my hoop.Dit is gebaseer op die feit dat ek bygevoeg'n std::string om'n klas en die toeken van'n waarde van'n ander std::string:

std::string hello = "Hello, world.\n";
/* exampleString = "Hello, world.\n" would work fine. */
exampleString = hello;

ongelukke op my stelsel met'n stapel stort.So basies ek nodig het om te stop en gaan deur al my kode en geheue bestuur dinge en vind uit waar ek geskroef.Die kodebasis is nog klein (ongeveer 1000 lyne), so dit is maklik doen-staat.

Nog steeds, ek is oor my kop met hierdie soort van dinge, so ek het gedink ek wil gooi dit uit daar.Ek is op'n Linux-stelsel en steek rond met valgrind, en terwyl weet nie heeltemal wat ek doen, dit het rapporteer dat die std::stringse destructor was'n ongeldige gratis.Ek het om te erken om die term "Hoop Korrupsie" van'n Google-soektog;enige algemene doel artikels oor hierdie soort van dinge sal waardeer word as goed.

(In voor rm -rf ProjectDir, doen weer in C# :D)

EDIT:Ek het nog nie dit duidelik gemaak, maar wat ek vra is maniere'n raad van die diagnose van hierdie soort van die geheue probleme.Ek weet die std::string dinge is reg, so dit is iets wat ek gedoen het (of'n fout, maar daar is Nie'n Probleem Met die Kies).Ek is seker ek kon kyk na die kode wat ek geskryf het en jy baie slim mense sou sien dat die probleem in geen tyd, maar ek wil hierdie soort van die kode analise aan my "toolbox", soos dit was.

Was dit nuttig?

Oplossing

Dit is relatief goedkoop meganismes vir moontlik die oplossing van die probleem:

  1. Hou 'n oog op my hoop korrupsie vraag - Ek is 'n m opdatering met die antwoorde as hulle skud. Die eerste is die balansering new[] en delete[], maar jy reeds dit te doen.
  2. Gee valgrind meer van 'n kans; dit is 'n uitstekende hulpmiddel, en ek wil net dit beskikbaar onder Windows. Ek vertraag net jou program af met sowat die helfte, wat is redelik goed in vergelyking met die Windows ekwivalente.
  3. Dink oor die gebruik van die Google Performance gereedskap as 'n plaasvervanger malloc / nuwe.
  4. Het jy skoongemaak al jou voorwerp lêers en begin oor? Dalk moet jy jou make-lêer is ... "suboptimale"
  5. Jy is nie assert()ing genoeg in jou kode. Hoe weet ek dat sonder dit gesien? Soos vlos, niemand assert()s genoeg in hul kode. Voeg in 'n bevestiging funksie vir jou voorwerpe en noem dat op metode begin en metode einde.
  6. Is jy opstel Wall ? Indien nie, doen so.
  7. Vind jouself 'n pluis instrument soos PC-Lint . 'N Klein app soos joune kan inpas in die PC-pluis demo bladsy, wat beteken dat geen aankoop vir jou!
  8. Maak seker jy NULLing uit wysers na hulle deleteing. Niemand hou van 'n hangende wyser. Dieselfde gig met verklaar maar ongeallokeerde wysers.
  9. Stop met behulp van skikkings. Gebruik 'n vektor plaas.
  10. Moenie rou wysers. Gebruik 'n slim wyser . Moenie auto_ptr! Daardie ding is ... verrassende; sy semantiek is baie vreemd. In plaas daarvan, kies een van die Hupstoot slim wenke , of iets uit die Loki biblioteek .

Ander wenke

Ons het een keer het'n fout wat ontwyk al die gereelde tegnieke, valgrind, reinig, ens.Die ongeluk het net ooit gebeur het op masjiene met baie van die geheue en slegs op groot insette data stelle.

Uiteindelik het ons nagespoor dit af met behulp van debugger kyk punte.Ek sal probeer om die proses te beskryf hier:

1) Vind die oorsaak van die mislukking.Dit lyk uit jou voorbeeld kode, dat die geheue vir "exampleString" is wat beskadig, en so kan nie geskryf word.Laat ons voortgaan met hierdie aanname.

2) Stel'n breekpunt op die laaste bekende plek wat "exampleString" gebruik word of verander sonder enige probleem.

3) Voeg'n horlosie punt om die data lid van 'exampleString'.Met my weergawe van g++, die string is gestoor in _M_dataplus._M_p.Ons wil om te weet wanneer hierdie data lid veranderinge.Die GDB tegniek vir hierdie is:

(gdb) p &exampleString._M_dataplus._M_p
$3 = (char **) 0xbfccc2d8
(gdb)  watch *$3
Hardware watchpoint 1: *$3

Ek is natuurlik die gebruik van linux met g++ en gdb hier, maar ek glo dat die geheue kyk punte is beskikbaar met die meeste debuggers.

4) gaan Voort totdat die horlosie punt is veroorsaak:

Continuing.
Hardware watchpoint 2: *$3

Old value = 0xb7ec2604 ""
New value = 0x804a014 ""
0xb7e70a1c in std::string::_M_mutate () from /usr/lib/libstdc++.so.6
(gdb) where

Die gdb where opdrag sal gee terug'n spoor te wys wat gelei het tot die verandering.Dit is óf'n volkome wettige wysiging, in welke geval net voortgaan - of as jy gelukkig is dit sal wees om die verandering as gevolg van die geheue korrupsie.In die laasgenoemde geval, jy moet nou in staat wees om te hersiening van die kode wat is regtig die oorsaak van die probleem en hopelik sal dit regmaak.

Die oorsaak van ons fout was'n verskeidenheid toegang met'n negatiewe indeks.Die indeks is die gevolg van'n gooi van'n verwysing na'n int' modulos die grootte van die skikking.Die fout was gemis deur valgrind et al.as die geheue adresse toegeken wanneer hy hardloop onder die gereedskap was nog nooit "> MAX_INT"en so het nog nooit gelei het tot'n negatiewe indeks.

Dit kan hoop korrupsie, maar dit is net so geneig om te stapel korrupsie. Jim se reg. Ons regtig nodig het 'n bietjie meer konteks. Dié twee lyne van bron hoef ons nie veel vertel in isolasie. Daar kan 'n aantal van die dinge wat veroorsaak dat hierdie (wat is die ware vreugde van C / C ++).

wees

As jy gemaklik is jy jou kode, jy kan selfs gooi dit alles op 'n bediener en plaas 'n skakel. Ek is seker jy sal baie kry meer raad dié manier ( 'n gedeelte daarvan ongetwyfeld verband hou met jou vraag).

Die kode was eenvoudig 'n voorbeeld van waar my program was die versuim (dit is toegeken op die stapel, Jim). Ek is nie eintlik op soek na 'Wat het ek verkeerd gedoen, maar eerder' hoe kan ek diagnoseer wat ek verkeerd gedoen het. Leer 'n man om vis te vang en alles wat. Alhoewel kyk na die vraag, het ek nie dat duidelik genoeg gemaak. Dankie tog vir die edit funksie. : ')

Ook, Ek het eintlik vaste die st :: string probleem. Hoe? Deur dit te vervang met 'n vektor, die opstel van, dan weer die vervanging van die string. Dit is konsekwent daar gekraak, en dat vaste selfs al is dit ... kon nie. Daar is iets nare daar, en ek is nie seker wat. Ek wou hê om die een keer dat ek die geheue met die hand te wys op die wal te gaan, al is:

 this->map = new Area*[largestY + 1];
 for (int i = 0; i < largestY + 1; i++) {
     this->map[i] = new Area[largestX + 1];
 }

en die verwydering van dit:

for (int i = 0; i < largestY + 1; i++) {
    delete [] this->map[i];
}
delete [] this->map;

Ek het nie toegeken 'n 2D-skikking met C ++ voor. Dit blyk te werk.

  

Ook, Ek het eintlik vaste die st :: string probleem. Hoe? Deur dit te vervang met 'n vektor, die opstel van, dan weer die vervanging van die string. Dit is daar konsekwent gekraak, en dat vaste selfs al is dit ... kon nie. Daar is iets nare daar, en ek is nie seker wat.

Dit klink asof jy regtig skud 'n hoender op dit. As jy nie weet waarom Dit is nou besig, dan is dit nog steeds gebreek, en pretty much gewaarborg om jou weer te byt later (nadat jy selfs meer kompleksiteit het bygevoeg).

Hardloop Reinig.

Dit is'n naby-magiese instrument wat sal die verslag wanneer jy clobbering geheue jy moet nie raak, lek geheue deur nie bevry dinge, dubbel-bevry, ens.

Dit werk op die masjien kode vlak, so jy hoef nie eens om die bron-kode.

Een van die mees genotvolle verkoper konferensie-oproepe wat ek ooit op was toe Reinig het'n geheue lek in hul kode, en ons was in staat om te vra, "is dit moontlik dat jy is nie bevry geheue in jou funksie cat()" en hoor die verbasing in hul stemme.

Hulle het gedink ons is ontfouting gode maar dan moet ons toelaat dat hulle in die geheim, sodat hulle kan hardloop Reinig voor ons het om te gebruik om hul kode.:-)

http://www-306.ibm.com/software/awdtools/purify/unix/

(Dit is redelik duur, maar hulle het'n gratis eval laai)

Een van die ontfoutingstegnieke wat ek gereeld gebruik (behalwe in gevalle van die mees ekstreme vreemd) is om te verdeel en oorwin. As jou program tans nie met 'n paar spesifieke fout, verdeel dan in die helfte in een of ander manier om te sien of dit nog steeds dieselfde fout. Dit is duidelik dat die truuk is om te besluit waar om jou program te verdeel!

Jou voorbeeld soos gegee nie genoeg konteks wys om te bepaal waar die fout mag wees. As enigiemand anders was om jou voorbeeld te probeer, sou dit reg te werk. So, in jou program, probeer die verwydering van soveel van die ekstra dinge wat jy het nie vir ons wys en kyk of dit werk dan. As dit so is, en voeg dan die ander kode terug in 'n bietjie op 'n slag totdat dit begin om te misluk. Dan, die ding wat jy net bygevoeg is waarskynlik die probleem.

Let daarop dat indien u program is multi, dan is jy waarskynlik 'n groter probleme. Indien nie, dan moet jy in staat wees om dit nou af op hierdie manier. Sterkte!

Anders as gereedskap soos Boundschecker of te suiwer, jou beste bet by die oplossing van probleme soos dit is om net regtig 'n goeie by die lees van kode en vertroud is met die kode wat jy werk op geword.

Memory korrupsie is een van die moeilikste dinge om op te los en gewoonlik hierdie tipe van probleme word opgelos deur die besteding van ure / dae in 'n debugger en merk iets soos "hey, wyser X gebruik word nadat dit verwyder!".

As dit help nie, dit is iets wat jy beter op as jy ondervinding op te doen kry.

Jou geheue toekenning vir die skikking lyk korrek, maar maak seker dat jy al die plekke waar jy toegang tot die skikking te kyk.

Jou kode as ek kan sien het geen foute. Soos reeds gesê meer konteks nodig is.

As jy nog nie probeer het, installeer gdb (die gcc debugger) en stel die program met G. Dit sal stel in die opsporing van simbole wat gdb kan gebruik. Sodra jy gdb geïnstalleer run dit met die program (GDB). Dit is 'n nuttige cheatsheat vir die gebruik van gdb.

Stel 'n breekpunt vir die funksie wat die vervaardiging van die fout, en sien wat die waarde van exampleString is. Ook dieselfde doen vir watter parameter jy verby te exampleString. Dit moet jy ten minste te sê as die std :: snare is geldig.

Ek het gevind dat die antwoord van hierdie artikel om 'n goeie gids oor wysers wees.

Sover ek kan vertel jou kode korrek is. Veronderstelling exampleString is 'n st :: string daardie klas omvang het soos jy beskryf, jy behoort te inisialiseer / toewys dit so. Miskien is daar 'n paar ander kwessie? Miskien 'n uittreksel van die werklike kode sal help om dit in konteks.

Vraag: Is exampleString 'n verwysing na 'n string voorwerp wat gemaak is met nuwe

Gelisensieer onder: CC-BY-SA met toeskrywing
Nie verbonde aan StackOverflow
scroll top