Ez Gcc hiba?

 ( emberk | 2012. szeptember 29., szombat - 9:50 )

Van két változóm. x_x2, y_y2, amik kezdetben double értékek, egy illesztés miatt majd int-et készítenék belőlü, mert memóriacímre hivatkozok velük, súlyozva. Lényegében egy viszonylag bonyolultabb képlet eredménye. Amikor elkezdtem a gdb-vel kiirattatni ezt a marhaságot kapom, ugyanis nem értettem, hogy hogyan hivatkozhatok olyan memóriacímre ami címzési hiba lenne. A vicc az, hogy ugyanezt a kódot már 1 éve használom, de egy frissítés óta jön ez a sületlenség.

Folyomány, ami piszokul nem logikus.

A lényeg, hogy ez a program egy x*1000,y*1000-es képet dolgoz fel. A vicc az, hogy ha gimppel készítem a png-t amit feldolgozok akkor lefagy, ha pdf-ből exportálom akkor nem. Kutya legyek ha értem. Pedig pixelről pixelre ugyan az.

Egy gdb kimenet: Valakinek van ötlete, hogy mi lehet a gond?

--memory-breakpoint__ 16871733 : x_x2 M= emory at 0x7fffd2567850, size 0x28 = 40
+0 0x00007FFFD2567850 497.1382613
00 y_y2 = 00 00 00 00 00 00 00 00 340.6499497
x_x2 = 00 497.1382607
y_y2 = 00 340.6499497
x_x2 = 00 00497.1791549
y_y2 = 00 00340.6590548
x_x2 = 00 497.1791542.
y_y2 .=... ...........
340.6590548
x_ +16 0x00007FFxF2 D=256 7860 00 00 497.1791542
y_y2 = 0340.65905480
x_x2 = 00497.1791535
y_y2 = 340.6590548
x_x2 = 00 00 00 497.22004530
y_y2 = 0 00340.6681624
x_x2 = 497.2200446
y_y2 = 0340.66816240
x_x2 = 0497.2200446
y_y2 = 0340.6681624
x_x2 = 00 497.2200439
y_y2 = 00 340.6681624
x_x2 = 00 00 0497.2609333
y_y2 = 0340.6772725
x_x2 = ......497.2609326.
y_y.........
+32 2 = 0x00007FFFD2567870 00 00 0340.67727250
x_x2 = 00 00 497.26093260
y_0 00 y00 2 = ...340.6772725.
....
x_x2 =
--memory-breakpoint__ 16871732 : 497.2609319M
eym_oy2 r=y at 0x7fffd2567800, size 0x28 = 40
+0 0x00007F340.6772725
FFxD2_5x67280 0 = 00 00 00 00 00 00 00497.3018188
y_y20 0 = 00 00 00 00 00 340.686384900
x_x020 = 00 ................
+16 0x00007F497.3018181
y_FyFD2256 781=0 00 00 00 00 00 00 00340.6863849
x_00 00 x020 = 00 00 00 00 00 80497.3018181
y_y2 = ...............340.6863849
x_x2 = �
+32 0x00007FFFD25678497.3018175
2y0 _y2 = 00 00 00 00 00 00 00 0340.68638490
x _ x2 = ........ 497.3427019
y_y2 =
340.6954998
x_x2 =
--memory-breakp497.3427013
y_y2 = oint__ 16340.69549988
x_x2 = 497.3427013
y_y2 = 340.6954998
x_x2 = 7793.9310326
y_y1273 1= : Memory at 0x7fff123.7538677

http://pastebin.com/V8iz73V4

Ez a függvény száll el.

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

Lefordítottad -Wall-lal? Jelez valamit?

Igaz.... Ez még nem volt meg lesz.

Megvolt:
Ninc sérdemi + info. Ugyan ez. Megtudtam, hogy hol száll el a kóde de ezt eddig is tudtam, de az elszállás már előtte megvan, mert az x_x2 már hibás értéket kap előtte.

------
3 fajta matematikus létezik. Aki tud számolni, és aki nem.

Akkor jöhet egy nagyobb puska: valgrind.

Off: túl sok a floor(), dxk2=1.0-dxk1. A pixel_meret helyett a reciprokát használnám, szorozni sokkal gyorsabban lehet, mint osztani. A két memo index között is konstans a távolság, egy 1D-s memo-val és kézzel indexelve jóval gyorsabb lenne az indexelés (ha ez számít).

Első körben átláthatóra szeretném írni a kódot, de megfogadom a tanácsaidat.

------
3 fajta matematikus létezik. Aki tud számolni, és aki nem.

Nekem akkor szoktak ilyen titokzatos dolgok történni, amikor egy teljesen mással kapcsolatos rész belerombolt a stack-be (vagy egy olyan területbe, ahol pointerek vannak). Tapasztaltam már olyat, hogy egy réges-rég beépített hiba csak egy gcc vagy lib verzió váltáskor, esetleg egy -O módosításkor jött elő. Ilyenkor rendszerint egy hosszú, kód-darabolós hibavadászat kezdődik, mert a hiba teljesen máshol van, mint a következménye, amit látunk. Persze nem láttam a kódot, így nyilván csak találgatni tudok...

Pointerek azok vannak rogyásig. Egy rakás power-thread (lehet helytelen megfogalmazás, én hívom így) megy egymás mellet megosztott 4d-s memóriaterületen. Akkor vadászok.

------
3 fajta matematikus létezik. Aki tud számolni, és aki nem.

Segítene, ha a C kódrészletet is megosztanád. Elég csak a lényegi rész.

Pasetbin-elve az elszálló kód. :) Egyébként pedig Siman meghívom az Ft függvényt egy threadból, a megfelelő paraméterekkel.
double eredmeny=xyz*Ft(....);

------
3 fajta matematikus létezik. Aki tud számolni, és aki nem.

- az x_x2 nem tul sok ok miatt kaphat hibas erteket. a meghatarozo ket valtozoval mi a helyzet?
- double tipusu valtozo eseten miert hasznalsz == operatort?

---
Egy jól megállapított probléma félig megoldott probléma.
- Charles Kettering

Nem használok double-nél ==-t. Egyébként nem szabad? Mert itt nincs, de ha pl azt szeretném, hogy if(x_x2==y_y2) nekem fontos akkor ezt nem tehetem meg double-ként?

------
3 fajta matematikus létezik. Aki tud számolni, és aki nem.

A különbséget hasonlítsd össze, ha kisebb valaminél, akkor elfogadod.

Értem. DE ha nekem csak az x_x2-y_y2==0 a jó? Nem akadékoskodok, de tényleg ez a helyzet.

------
3 fajta matematikus létezik. Aki tud számolni, és aki nem.

Érettem megfogadom :)

------
3 fajta matematikus létezik. Aki tud számolni, és aki nem.

Értem lebegőpontosnál intervallum. Ilyen az, ha az ember autodidakta tanulja a dolgokat. Fontos finomságok felett elsiklik. Tiszta sor, hogy miért, hisz a pontosság nem tökéletes sehol, így gyak soha nem leysz egyenlő.

------
3 fajta matematikus létezik. Aki tud számolni, és aki nem.

Amúgy világos, hogy az első cikk is elég lett volna ide, csak közben találtam még, és hogy ne legyen hiábavaló a keresgélésem, beírtam :-)

A lényeget már elmondták, de itt egy különösen látványos példa:

http://pastebin.com/zR1bfxWU

Ha pedig mélyebben meg akarod érteni a témát, akkor keress rá arra, hogy "what every computer scientist should know about floating point arithmetic".

A BME-n vizsgán ilyen hiba halálfejet ért - azonnal kivágtak vizsgáról.

Soha nem volt vizsgám programozás egyik fajtájából sem :) Tiszta szerencse.

------
3 fajta matematikus létezik. Aki tud számolni, és aki nem.

de, hasznalsz

if (xy==1 && futhat)

a fuggveny parameteristajaban xy double tipusu

nem egesz szamok hasonlitasa eseten faluhelyen szokas az epsilonra is gondolni

---
Egy jól megállapított probléma félig megoldott probléma.
- Charles Kettering

xy int típusú.

------
3 fajta matematikus létezik. Aki tud számolni, és aki nem.

hm, elneztem :)

---
Egy jól megállapított probléma félig megoldott probléma.
- Charles Kettering

Én szoktam lebegőpontos számnál is egyenlőségvizsgálatot alkalmazni, teljesen jól működik, ha az egyik számot a másikról másolja az ember (vagy nem). Gond csak akkor lehet, ha különbözőképpen akarod megkapni (majdnem) ugyanazt.

Nem szeretnek udvariatlan lenni, de ennel rondabb kimenetet mar regen lattam. Nem lehetne valami emeszthetobb formaba onteni?

hogyan allokálod és inicializálod a memo -t? betennéd pontosan, mert valahol itt lehet a gubanc.

egyéb
- jól látom, hogy nem mindig adsz vissza értéket a függvényből? csúnya...
- tipp: cseréld le a memo tömb indexelését egy függvény hívásra, ahol ellenőrzöd az egyes indexeket, mielőtt belefirkálsz a tömbbe. megtalálod a hibát percek alatt.
- tipp: sokkal jobb lenne memóriafolytonos allokálás, mint ezekkel a pointerekkel szórakozni, teljesítményben is jobb lehet

1: Mindíg ad vissza értéket, mert az xy csak 0, vagy 1 lehet, ha valamikor 3d-s model lesz (kénytelen leszek, ha lesz mágneses tér) akkor kiterjesztem a 3d-s variációk összes lehetőségére.
2: ilyen már volt, az Ft függvény elején volt egy rész ami ellenőrizte az értékeket, amikor hozzányúlok a memóriatömbhöz akkor lesz vele valami. gdb is akkor adta ki ezt amikor címzés után ellenóriztem az értéekeket.
3: A memórifolytonosság később lesz, mert elősör a matematiai módon átlkáthatóan szeretném megcsinálni. Ha úgy már megy akkor jon a gyorsítás.

------
3 fajta matematikus létezik. Aki tud számolni, és aki nem.

Megint nem szeretnek udvariatlan lenni, de nem lehetne, hogy hasznalhato infot adj, ha mar kerdezel valamit? ;)
- Hogyan allokalod memo-t? Remelhetoleg nem a stacken van.
- Miert nem ellenorzod az indexek erteket mielott hozzanyulsz a tombhoz? Bar allitolag megtetted, nem ertem hogy minek probalod piszkalni a memoriat, ha mar az egyik index nagyobb, mint kellene? Egyebkent assert a baratod ;) x_x2 ill. y_y2 keves, mivel mindkettot szamolod, jobb lenne xx, yy es pixel_meret erteket szinten kiiratni, lehetoleg egy sorba, hogy lassunk is valamit ...

ui:
- 64 biten a double->int cast sem eppen perfekt
- Ha memory corruption-ra vetul a gyanu arnyeka, gdb helyett valgrind a baratod

1:Nem vagy udvariatlan. Nem vagyok profi programozó, amolyan mellékágkét megtanultam, de az alapok hiányoznak sok helyen. Örömmel veszem a jó szándékú kritikát. Igazad van. Átnézem ilyen szempontbl a kódokat. nem is lesz nagy módosítás, hogy mindíg kapjak értéket.

2:Nem a stack-en van. simán 1-el fölötte definiálok egy 3-szoros indirektségű mutatót, és 3 egymásba ágyazott for ciklussal lefoglalom, és teletömöm 0.0-kal. egy következő függvény bedolgozza egy képből az adatokat, majd jön a runge-kutta4, aminek az Ft az egyik része.

3:az indexértékeket 1-el fentebb ellenőrzöm, még xx, és yy-ként ha ezek túl vannak a tartományon, akko rmeg sem hívom a függvényt a pixel_merete pedig konstans, amire fentebb javasolták, hogy a reciprokát használjam majd, mert a szorzás gyorsabb, ezt meg fogom fogadni.

ui:
1: ezen ne múljon a pozíció nem anyira fontos, legyen float bőven elég pontos az is.
2: kipróbálom.
------
3 fajta matematikus létezik. Aki tud számolni, és aki nem.

"egy következő függvény bedolgozza egy képből az adatokat"
Akkor nezd meg azt, mit csinal, mert nem kizart, hogy ott tortenik valami feluliras. Ez megmagyarazna, miert viselkedik maskepp a kulonbozo fajloknal (javasoltak lejjebb is).

az indexértékeket 1-el fentebb ellenőrzöm, még xx, és yy-ként ha ezek túl vannak a tartományon, akko rmeg sem hívom a függvényt a pixel_merete pedig konstans
OK, ha jo a check en elhiszem ;) viszont ha a stack felulirodik, akkor a fuggvenyparameterek is felulirodhatnak es igy esetleg semmi nem lesz az, aminek korabban latszott ;) Tegyel be egy assertet a memoria hivatkozas ele is szerintem, nem kell felni, nem harap ;)

" Mindíg ad vissza értéket, mert az xy csak 0, vagy 1 lehet,"

nem. ez egy fekete doboz, nem bízik meg a külvilágból származó paraméterekben.
legalább egy assert(xy==0 || xy==1) a függvény elejére, lécci

Megfogadom a tanácsodat.

------
3 fajta matematikus létezik. Aki tud számolni, és aki nem.

egy code reviewn azert nem menne at :-)

--
NetBSD - Simplicity is prerequisite for reliability

Nincs is még kész minden :) De aláírom. Nm a legszebb megoldás, viszont matematikailag könnyen átlátom.

Ui:
Egyébként szívesen veszek minden programozástechnikai kritikát, mert én nem vagyok programozó. Fizikával foglalkozok. A programozói ismeretem maximum középhaladó szinten vannak. Többnyire amiken dolgozom programozás szempontjából könnyű feladatok, matematika, és fizika szempontjából kevésbé.

------
3 fajta matematikus létezik. Aki tud számolni, és aki nem.

x_x2, és y_y2 (sőt xx2 és yy2 is) lehetne rögtön int. Vagy unsigned int.
Feleslegesen van ezekből kétféle ha jól látom. Én kb így írnám meg a fv-t (ha máshoz nem nyúlhatok :) ):

double Ft(double ***memo,double xx, double yy, double fajlagos_t, double pixel_meret, int  xy, bool futhat)
{
    int x_x2=(int)(xx/pixel_meret);
    int y_y2=(int)(yy/pixel_meret);

    if (!futhat)
        return 0.0;
  
    assert(xy == 0 || xy == 1);
    if (xy == 0) {
        double dxk1 = xx-floor(xx);
        return (dxk1*memo[x_x2][y_y2][2] + (1.0-dxk1)*memo[x_x2+1][y_y2][2])*fajlagos_t;
    } else if (xy == 1) {
        double dyk1 = yy-floor(yy);
        return (dyk1*memo[x_x2][y_y2][3] + (1.0-dyk1)*memo[x_x2][y_y2+1][3])*fajlagos_t;
    } 
}

Egyébként meg szinte biztos, hogy nem gcc hibáról van szó, hanem vagy túlindexeled a memo-t, vagy valamit valahol máshol, ami itt okoz galibát.
Ilyenekre alapból valgrindet szoktak ajánlani, de nekem a múltkor nem a valgrind hanem az efence (esetleg duma) segített...

Szerk.:
Ha ennyire érzékeny az input fájlra (gimp vs pdf export), nem lehet, hogy már beolvasásnál van valami galiba?

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee." -- Ted Ts'o

Lógok egy sörrel. Hihetetlen, de ezzel órák óta tökéletesen fut. Keresem az egyszerűsítéseken, és összevonásokon kívül a külömbséget , de semmi. Miután funkcionálsan befejezem a kódot én is át akoarom túrni, hogy mit lehet spórolni, tempót növelni... De tényleg bonyolúlt matematiai oldalról, és először ezt akartam végig gyúrni, úgy hogy ha ránézek a kódra akkor kapásból lássam a matematikai oldal. Örök hála. Az assert nélkül is tökéletes egyébként, de természetesen benne hagyom, mivel logikus, hogy kell, pusztán kíváncsi voltam.

------
3 fajta matematikus létezik. Aki tud számolni, és aki nem.

A "Hurra, eltunt a bug!" talan nem a legjobb szemleletmod a szoftverfejlesztesben, de ez legyen a te gondod, viszont:

Az assert nélkül is tökéletes egyébként, de természetesen benne hagyom, mivel logikus, hogy kell, pusztán kíváncsi voltam.

Nem, az assert nem kell, hanem csak javasolt, ugyanis nem hibakezelesre, hanem hibakeresesre szolgal! (ennek megfeleloen release verzioban semmi keresnivaloja, lasd NDEBUG)

"Nem, az assert nem kell, hanem csak javasolt, ugyanis nem hibakezelesre, hanem hibakeresesre szolgal! (ennek megfeleloen release verzioban semmi keresnivaloja, lasd NDEBUG)"

dehogy nincs! inkabb egy assert p != 0 failed, mint egy titokzatos page fault valahol negy fuggvennyel kesobb

--
NetBSD - Simplicity is prerequisite for reliability

Egy kenyerpiritonal esetleg, de szerintem meg ott sem. Nekem nincs kozom olyan szoftverhez, ahol egy runtime hibara a programmegszakitas a valasz. Ez nem megoldas, sem beagyazott rendszereknel, sem szerver alkalmazasoknal. Igy csak ismetelni tudom magam, az assert() hibakeresesre es nem hibakezelesre valo. Erdekes, hogy peldaul a CERT-nel sem latjak ezt maskepp. Persze tudom, mindenki hulye es inkompetens ;)

kivancsi leszek, mit szurnek le ebbol a programozok

---
Egy jól megállapított probléma félig megoldott probléma.
- Charles Kettering

Egesz pontosan mibol? ;) Vagy te is ugy gondolod, hogy nagymegbizhatosagu rendszerekben az assert() a megoldas a hibakezelesre?

nem ment at az ironia :)

---
Egy jól megállapított probléma félig megoldott probléma.
- Charles Kettering

lol, nem ;)

Némi refaktoringon és egyszerűsítésen kívül nem volt szándékomban mást változtatni, szóval elvileg nem javítottam semmi bugot.

Amikor ilyen fura dolgok történnek, mint ez, hogy egy nem lényegi változtatás megszünteti a bugot, az mindig azt jelenti, hogy a bug még mindig ott van, csak alszik...
Továbbra is erősen ajánlom a valgrind és társainak megismerését. Meg persze a kód átnézését elsősorban alul-felülindexelésre vadászva, mert ezek a toolok igen hasznosak, de nem találnak meg mindent.

Az assert meg olyan feltétel, ami nem teljesülés esetén egy hibaüzenet mellett terminálja a programot. Ha -DNDEBUG-ot kap a kód fordításkor, akkor az assert "eltűnik". Alapvetően igen hasznos elő- és utófeltételek, invariánsok ellenőrzésére, így fejlesztés alatt nem érhet meglepetés, release esetén meg nem jár lassulással.

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee." -- Ted Ts'o

Továbbra is erősen ajánlom a valgrind és társainak megismerését. Meg persze a kód átnézését elsősorban alul-felülindexelésre vadászva, mert ezek a toolok igen hasznosak, de nem találnak meg mindent.

Pontosan ezt teszem most. Köszi még egyszer. Én is erre következtettem,
------
3 fajta matematikus létezik. Aki tud számolni, és aki nem.

(1) Először is ki kell preparálni a hibát. Sajnos sokszor
előfordul, hogy a hiba csak egy idő _ELTELTE_ után jön el,
de ennek a ténynek is infotmációértéke van.

(2) Kövesd figyelemmel a processzorterhelést.

(3) Debug funkciók, változótartalom kiíratás csak akkor,
ha nagyon muszáj, különösen real-time közeli rendszereknél.
Én speciel a klaviatúra ledeket használom nyomkövetésre.
(3 bites számlálót lehet rá fölépíteni.)

(4) A hiba nem múlik el magától, _MINDIG_ a végére kell
járni. Előfordul például olyan, hogy kiíratod a változót
és megszűnik a hiba. Az ilyen típusú hibák gyökere ugyanaz,
mint a forditási opcióval / fordítócserével stb gyógyitott
hiba.

(5) Tesztelj sorról sorra!

(6) Ne sajnáld az időt a típuskonverzióra!

(7) A számlálóként (indexként) szolgáló adatok tipúsa unsigned legyen!

(8) Legyél tisztában a változók típusának MÉRETÉVEL (sizeof).

(9) Ne buheráld a fordítóprogramot, ha nem nagyon muszáj!

(10) Próbálj minél inkáb realisztikus helyzetben tesztelni
és a program kimenetéből következtetni a működési
anomáliákra! Mindig tudd, hogy milyen kimenetet vársz és
milyen kimenetek fordulhatnak elő a változók
szélsőértékeinél.

(11) Használd fel okosan a könyvtári fvnyek visszatérési
értékeit.

Üdv: meditor

> Sol omnibus lucet.

Egyébként - bár kétlem, hogy itt erről volna szó - egy két gcc optimalizáció is tud fura dolgokat művelni (-O3 pl.)