statikus változó törlése [MEGOLDVA]

 ( Kuvik | 2010. február 18., csütörtök - 20:15 )

A következő problémával kapcsolatban szeretnék segítséget kérni:

Nagyon leegyszerűsítve adott a következő szerkezet:

for(...){
   for(...){
     ...
     függvény(...);
     ...
   }
}

void függvény(...){
   ...
   static változó = 0;
   ...
}

Tehát, a függvényben van egy (vagy több) statikus változó, aminek az értékét csak addig szeretném megőrizni, amíg a belső ciklus fut. Amikor a belső ciklus végetér, és a külső ciklus lép egyet, azt szeretném, hogy a statikus változó kvázi újradeklarálódjon újradefiniálódjon, "resetelődjön".
Létezik erre valami egyszerű megoldás?

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ő.

Például a belső ciklus után 0-ra állítod.

Ott sajnos a függvény változói nem látszanak...
Szerintem globális változóval lehet csak megoldani.

--
Soli Deo Gloria

Szerintem globális változóval lehet csak megoldani.

Na ezaz ami nem megy.

Az a helyzet, hogy az egész dolog valójában sokkal bonyolultabb, legfelső szinten nagyjából így néz ki, ahogy a példában leírtam, de egyébként tele van még további, mélyebben lévő függvényekkel, azokban is statikus változókkal, statikus osztálypéldényokkal, stb., amiket mind törölni kellene.

Ha meg is csinálnám valahogy, akkor sem volna jó, mert a legfelül lévő függvénynek többé-kevésbé "önhordónak" kell lennie, egy dll-be lesz végül befordítva, és arra a környezetre, ahonnan meg lesz hívva, csak kevés befolyásom van.

Tehát kb. azt szeretném, hogy a függvényen belül lévő hierarchiában az összes statikus szar törlődjön, "gombnyomásra".

Ez így nem fog menni.
Vagy adsz a függvéynek egy int torold_a_statikus_valtozot paramétert, és a ciklusban ha kell, úgy hvod meg, hogy fuggveny(1), és akkor a függvény nem hajtja végre a dolgát, hanem törli a változókat.
De ez az egész elég ronda megoldás, írd újra szerintem.
Csináld meg úgy, hogy egy dinamikusan allokált struct -ot adsz át a függvénynek paraméterként, és ebben a struct -banvannak azok az adatok, amik kellenek.
Azt ehogyan sem fogod tudni elérni, hogy a függvényen kívül töröld annak a belső változóit, eleve nem látod a függvény belsejében levő névteret azon kívül, és ez nem holmi php meg egyebek, a c/cpp nem támogat ilyet, nincs erre megoldás.
Max hekkelni lehet, kitalálod valahogyan, hogy az adott architektúrán a memóriában hol tárolódnak a függvény lokális static változói, és azt a részt kinullázod.

Szomorúan hallom....

Tényleg elég jól néz ki, amit mondasz (meg a lentebbi példa), de nekem ide nem az igazi. Lehet, hogy részben alkalmazni tudom, de valószínűbb, hogy valami gányolás jön :(

Ha arra gondolsz, hogy leprogramozod azt, hogy megkeresed, hogy a memóriába hol van tárolva a függvény lokális static változója, és ezt törlöd, és ezt te ki is vitelezed, akkor emelem kalapom, de kérlek, hogy majd paste -old be a kódot ide is. :)

nem arra :)

Egy kalapemelést kapok? ;)
http://hup.pastebin.com/f1902a34b

Ezért mondjuk nem. :)

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

Ezért nem. (Ezt amugy barki megcsinalja, aki latott mar C pointer.)
A fuggveny() nem modosithato, lasd a kiirast. ;)

De a függvényen kívülről kellene. Ezért nem triviális, legalábbis nekem.

A függvényen belül pedig azért nem jó, mert buta, nem tudja, mikor van vége a ciklusnak. Egyelőre a függvény megpiszkálása csak korlátozott opció. Pl. új paraméterátadást nem szeretnék belerakni.

Ja, bocs, azóta már felfogtam, mi a probléma.
Csinálsz rá egy pointert, és azzal matatod. De mindenképpen csúnya megoldás.

Nem igazán jó, valójában sok statikus változó van, és a pointert is ki kell valahogy juttatni a függvény(ek)ből, ami a fentebbi okok miatt szintén nem járható.

Ha pointeresen csinálod, akkor úgy szép, hogy:

struct {
int valtozo1;
int valtozo2;
...
} MYDATA;

a függvényed:

void fuggveny(MYDATA* data) {
if(!data) return; /*ha NUL lett átadva, nem is próbálkozunk */

data->valtozo1 = ....;
}

adatokat tároló struct létrehozása ciklus elején:
MYDATA* data = (MYDATA*)malloc(sizeof(MYDATA))

ciklusban függvényhívás:
fuggveny(data);

ciklus vegen meg:
free(data);

+1, a belső ciklus után hívd meg a függvényt olyan paraméterekkel, amiktől nullázódik.

--
Debian - The "What?!" starts not!
http://nyizsa.uni.cc

Jelenleg nincsen olyan paraméterhalmaz, ami ezt csinálná, de ez egyébként sem nagyon járható, ld. feljebb.

Lehetőleg a függvénytől függetlenül kellene valamilyen megoldás.

-1, ez az igazi gányolás, csináljon egy struct -ot, amit átadogat a függvénynek.
Innen már csak egy lépés az OOP.

Teljesen igazad van, de én úgy vettem ki, hogy a függvény adott, nem változtatható a paraméterlista se. Nekem is jobban tetszene a fuggveny.reset(). :))

--
Debian - The "What?!" starts not!
http://nyizsa.uni.cc

void fuggveny(...,bool initit){
   ...
   static valtozo;
   ...
   if( initit ){ valtozo = 0; return ;}
}


//
for(...){
   fuggveny(...,true);
   for(...){
     ...
     fuggveny(...,false);
     ...
   }
}

ha a kodban nem tudod atirni a 'fuggveny' parszazezer elofordulasat, hogy a vegere biggyessz egy false erteket, akkor wrappelheto egy masik fuggvennyel vagy egy macroval, esetleg c++ -ban meg masik 200 egymastol fuggetlen megoldasa van a problemanak
----
szerk: most olvastam, hogy ne legyen uj parameter. akkor tekintsd targytalannak.

Nem akarja/nem tudja megvaltoztatni a fuggvenyt ugy, hogy legyen plussz egy parametere.

"esetleg c++ -ban meg masik 200 egymastol fuggetlen megoldasa van a problemanak"
Konkretan hogyan lehet c++-ban kinullazni egy fuggveny belso, static valtozoit?

Ezt is meg lehet trükközni, csak függvény helyett funktort kell használni, és akkor nem statikus változó van, hanem memberváltozó, és máris hepi.

Így ok, de arról volt szó, hogy nem lehet az eredeti függvényt változtatni.
Ha lehet változtatni, akkor 1000 masik megoldas is van, mint athekkelni az egeszet, hogy functort hasznaljon.

Én fejlesztem a függvényeket is, szóval elvileg lehetséges a váltotatás, ami akadályoz:

1. A végleges formájuk a mostani, tehát, ha magamnak össze is hekkelem valahogy a rendszert, az nem lesz jó a végleges változathoz, ha ez a függvények feltúrásával jár.

2. Sok meló. Végigmenni az összes szaron, mindenféle változók az egész függvényhierarchiában szanaszéjjel, olyan finomságokkal fűszerezve mint pl. statikus osztálypéldányok, ahol még maga a "reset" sem annyira egyértelmű, mint egy közönséges változónál (talán a destruktort kellene meghívni, aztán a kövekező ciklusban újra létrejönnek, vagy nem tudom), meg esetleg nézni azt, hogy közben mit barmolok széjjel azzal, hogy beletákolom egy kvázi "init" állapot lekezelését (ha így csinálnám), nem sok kedvem van hozzá.

http://hup.hu/node/83288#comment-960138

A helyedben újraírnám....
De a te programod, neked kell eldönteni.
A kérdésedre válaszolva: nem, vagy csak nagoyn-nagoyn-nagy kompromisszumok árán kivitelezhető, és eleve nagy tervezési hibát mutat.

+1, szerintem se ártana egy komolyabb revise, mert később még nehezebb lesz

Ez érdekelne egy kicsit bővebben. Nem ismerem, vagy lehet, hogy igen, de a kifejezések legalábbis nem ismerősek.

Ja, igen így világos, de szintén nem jó nekem :)

ha sima C, akkor tobb piszkos (architecture-dependent) megoldas kepzelheto el

1) ha a fuggveny masik modulban van, akkor a static deklaracio egy irhato, masik memorialapra esik, compile-map segitsegevel megmondhato hova, azt fel tudod venni, tudod kivulrol manipulalni. (a c nem mas, mint egy gazos assembly) Ez persze kevesbe jo, ha az a modul zart forrasu, nem te forditod vagy valtozik, vagy olyan az architectura, hogy meg a static is befer egy regiszterbe.

2) ha external dynamic lib (.so) -ban van a fgvny, akkor dlclose();dlopen(); a kulso ciklusban.

3) kerjed a fuggveny fejlesztojetol a thread safe valtozatot:)

Nem sima C, hanem C++.

1) Egyelőre nem lenne probléma, de később lehet, hogy más architektúrán is kellene, hogy működjön, úgyhogy inkább nem ebbe az irányba mennék el (bár, akármennyire is mondják itt néhányan, hogy ez gányolás, szerintem szép, igazi hack :)

2) Ezen már én is gondolkodtam, de néha szükségem van néhány globális változóra, (amiket csak eseti jelleggel írok bele a kódba, de ettől még fontosak) és ha külső lib-ben van a függvény, akkor azthiszem buktam a globális változókat, de FIXME.

3) Én vagyok a függvény(ek) fejlesztője és nagyon úgy néz ki, hogy ilyesmit fogok kérni magamtól, ezzel csak az a baj, hogy sok, vagy legalábis ebből a szempontból bonyolult a kód, ráadásul konzisztens megoldás kellene, mert később, ahogy fejlődik tovább, újabb olyan feature-k kerülnek majd bele, amiknek kell static változó, és ezért jó lett volna olyan megoldást találni, ami a már meglévő és a csak ezután elkészülő függvényeknek is minimális módosításokkal megfelel. Arról nem is beszélve, hogy legalább 20-30 munkaórát meg tudnék spórolni, ha nem kellene az egész static koncepciómat felforgatni.

Ne haragudj, azt kell, hogy mondjam, hogy evvel a static koncepcióval el van baltázva az egész.
Amúgy arról nem volt szó, hogy C++ programot írsz.. ;)
Javaslatom:
A fuggveny() -t valtsd ki egy osztallya.
Gondolom ez a fuggveny szamol valamit.
Az osztalyodnak legyenek privat adattagjai, amiket a konstruktor inicializál.
A for ciklusok előtt létrehozod az osztályt, a végén törlöd.

"A for ciklusok előtt létrehozod az osztályt, a végén törlöd."

Nem jó, a függvény hordozhatóságával / későbbi felhasználásával kapcsolatos követlemények miatt.

Idézet:
akármennyire is mondják itt néhányan, hogy ez gányolás, szerintem szép, igazi hack :)

Pedig azokra kellene, hogy hallgass, akik azt mondjak, mert igazuk van. Ez ganyolas, tulajdonkeppen egy tervezesi zsakutca.

20-30 munkaórát meg tudnék spórolni, ha nem kellene az egész static koncepciómat felforgatni

Az nagyon kevés. Ráadásul amit itt megspórolsz, később el fogod veszteni. Sőt, még többet is.

+1

Most még a fejlesztés kezdeti szakaszában vagy, és máris hackelni készülsz. Ilyenkor automatikus kell legyen a refactoring.

Ha 2 év fejlesztés után valami apró új feature miatt kéne 3 hónapig dolgoznod még megérteném, de így...

Hidd el megéri. Ha az átalakítás jól sikerül, 2 nap múlva már azt veszed észre, hogy: "jééé, egy hete még mennyit szívtam ezzel a problémával, most meg 2 sor az egész".

Tisztább, szárazabb, biztonságosabb érzés...

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

Eh, ez könnyű pedig, főleg C++-ban, ahol lehet referenciákkal, és úgy transzparens.

int* _var() {
  static int i=0;
  return &i;
}
 
void func()
{
  static int* var=_var();
  ...
}

Ez az én szempontomból hasonló ehhez: http://hup.hu/node/83288#comment-959878
és a korábban említett dolgok miatt nem, vagy csak nehezen járható megoldás.

Bárhogy nézem a problémádat, csak az látszik, hogy újra kéne írnod az egészet.
Már az gyanús kell legyen ha c++-ban elkezdesz lokális statikus változókat használni. Én pl egy hirtelen felindulásból elkövetett debug kódon kívül sose használok ilyesmit.

Ökölszabály: ha egy függvény két futása között átmeneti adatokat kell tárolnod, akkor c++-ban gondolkozás nélkül osztályt kell írni. (A funktor is egy osztály.)
És lehetőleg osztályon belül is kerülni a statikus adattagokat...

Egyébként C-ben is ez a mutatós struct-os megoldás játszik. Nézz meg kb bármilyen C-s (akár dinamikus) lib-et. Szinte mindig van valami init fv, ami visszaad egy mutatót, amit aztán cipelned kell minden fv híváshoz.
(Miközben gyakran teljesen el van rejtve előled, hogy mire is mutat az a mutató.)

A statikus változó már csak azért sem jó, mert a legtöbb lib-nél el lehet képzelni olyat, hogy egy programon belül, de egymástól függetlenül kétszer is akarod használni, akár átfedésekkel. A statikus változók rögtön összekavarodnának...

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

Nos, a statikus változók nagyrésze valójában nálam sem statikus változó, hanem osztály van, és az osztálypéldányok statikusak (ez egyébként pont azért van így, amit írtál, hogy több példányban se kavarodjanak össze). De igazából ez mindegy, ebből a szempontból ugyanaz a probléma.

"ebből a szempontból ugyanaz a probléma."
Igen, a problema ugyanaz. Eloszor elrejted a valtozodat egy fuggveny torzseben, majd megprobalod "kivulrol" piszkalni es szerinted ez igy jo, ez a problema ;)

Nem jó, de nem nagyon van megoldás. Amiket írtok, hogy hogyan kellene ezt kezelni, az nagyon szép meg jó, nem is akarok vitatkozni vele, csak éppen konkrétan az én problémámra nem jó. Technológiailag jó, de a feladat jellegéből adódóan nem jó.

"a feladat jellegéből adódóan nem jó"
Amennyiben az a feladat, hogy hogyan tudod magad hibas tervezessel tokon szurni, arra a tobbiek altal vazolt eddigi javaslatok tenyleg nem nyujtanak megoldast :p Amit viszont nem ertek, ha mar egyszer ragaszkodsz az eddigi megoldashoz, akkor miert annyira problemas a fuggvenyednek egy "init" flaget atadni?

Mert sok helyen kell és nem mindenhol oldható meg egyszerűen így. De valószínűleg valami ilyesmi lesz a megoldás, kiegészítve feltételes fordításos makrókkal, hogy ha éppen nem kell, akkor minél kevesebb gányolás forduljon be.

Egyebkent a programod tobbszalu? ;)

"Mert sok helyen kell és nem mindenhol oldható meg egyszerűen így."

Legyen default parameter, C++-ban lehet mar ilyet.
void fuggveny (bool toroljem_a_belso_static_szarjaimat = false) {

if (toroljem_a_belso_static_szarjaimat) {
// torlom oket
}

}

Fuggveny meghivasa, ahol torolni kell:

fuggveny(true);

Fuggveny meghivasa, ahol nem kell torolni a belso szarokat:

fuggveny();

Tehat ahol nem kell piszkalni, ott nem kell a kododban modositani a fuggenyhivast.

Keress a feladat jellegének megfelelő algoritmust, és akkor nem kell gányolni. Ha az algoritmus megtervezésénél alacsonyra tetted a mércét, akkor a programod minőségét is felülről korlátoztad.

-----
Nem vagyok gondolatolvasó, így nem tudom mit akartál írni. Ha nem szeretnéd, hogy félreértsenek, akkor fogalmazz pontosan.

"de a feladat jellegéből adódóan nem jó"

Ezt egyrészt nehezen hiszem, másrészt ha igaz, hogy ez ennyire speciális helyzet, akkor érdemes lenne többet elmondanod ebből a szupertitkos projectből, hogy segíteni tudjunk.

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

Naszóval:

http://en.wikipedia.org/wiki/Infinite_impulse_response

a problémát főleg az ilyen szűrők implementációja jelenti, főleg ha magasabbrendűekről van szó.

Ezek sok helyen szerepelnek a kódban (ráadásul több különöző változatban, ami változatonként eltérő számú statikus tagot feltételez), ezért készítettem egy szűrő-osztályt, amiből elég létrehozni egy új példányt, ha be akarok tenni egy újabb ilyen szűrőt. Mivel ezekre a legkülönbözőbb helyeken és kontextusban lehet szükség, ezért nem egyszerű csak úgy "kiszervezni" az állapotok kezelését a fő függvényemen kívülre, pl. elég ha csak azt nézzük, hogy egy új szűrő beépítése (vagy egy meglévő módosítása) ami egyáltalán nem ritka dolog, hány helyen implikálna változtatást.

Egyébként, lehet, hogy igazad van és el kellene kerülni a statikus változók vagy osztálypéldányok használatát, ez nyilván bevett pl. ha valami "userspace" dolgot csinálunk, de itt nem egészen ilyen feladatról van szó, a szűrők implementálása statikus változókkal teljesen industry-standard, szóval ezért sem szívesen változtatnék ezen (a fentebb részletezett dolgokon kívül).

szerk.:

a statikus változók használata ebben az esetben nem azért industry-standard, mert valaki egyszer a saját pillanatnyi szükségletei szerint vagy öntörvényűen kitalált valami hülyeséget és úgy maradt, hanem mert a szűrők működési elvéből adódik (ld. link), hogy meg kell őrizniük az állapotukat, ez pedig kézenfekvően statikus változókkal oldható meg.

> ...meg kell őrizniük az állapotukat, ez pedig kézenfekvően statikus változókkal oldható meg.

Igen, C-ben. C++-ban az osztály pont erre való. Privát adattagokat nyugodtan alkalmazhatsz a belső állapotváltozók reprezentálására, pont úgy viselkednek, ahogy neked kell.

--
Debian - The "What?!" starts not!
http://nyizsa.uni.cc

Igen, így is van implementálva. De ettől még a probléma ugyanaz.

Vagy másképpen megfogalmazva:

ha az adott példány nem statikus, "elpusztul" amikor a létrehozás helyéről kikerül a végrehajtás (FIXME).

Ha lokális változó, akkor igen.

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

Valamit szamolni kell ezek szerint.

csinlaj egy class-t, valami ilyet:
http://hup.pastebin.com/f49f2ad25

Igen, valószínűleg iylesmi lesz.

De nemcsak neked mondom, hanem a többieknek is, hogy nem azzal van a bajom, hogy nem tudom, hogy hogyan kell egy olyan megoldást készítenem mint ami pl. a te példádban le van írva, hanem, hogy nem ilyet szeretnék, hanem olyat, amilyet már korábban leírtam.

Más kérdés, hogy eddig úgy néz ki, hogy nem fog sikerülni.

Ertem en, nem is fikaztalak, segiteni probalok. :)
Viszont arra en is ra akarok vilagitani, hogy alapvetoen elhibazottan epitetted fel az eddigi programodat (az alapjan, amit tudunk rola).
Ha nincs sok 10 ezer programsorod, akkor erdemes ujrakezdeni, a megszerzett tapasztalatokat felhasznalva, hogy egy jo valami suljon ki belole. :)

"Viszont arra en is ra akarok vilagitani, hogy ... erdemes ujrakezdeni"

Na, ez már dereng :)

Egyébként tényleg nem egy programtervezési mestermű, de azt sem gondolnám, hogy alapjaiban elhibázott lenne, vagy, hogy magamat hibáztassam ezért, mert amikor elkezdtem erről a feature-ről még szó sem volt, ez nem rég jelent meg mint újabb igény.

mert amikor elkezdtem erről a feature-ről még szó sem volt

Ha szarkasztikus lennek azt mondanam, hogy: "isten hozott a valo eletben" :)

hanem, hogy nem ilyet szeretnék, hanem olyat, amilyet már korábban leírtam.

értjük, te az a fajta vagy, aki még ha érti is, hogy lehetetlent kíván, akkor is ragaszkodik hozzá. értsd meg, hogy az, amilyet szeretnél, az nem tud működni. mivelhogy nem is arra való, mint amire szeretnéd használni.

+1

Ha ez ennyire industry-standard, akkor mi annak a standard módja, amit te szeretnél?

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

Az, hogy le van kezelve a reset (valószínűleg nekem is ezt kell majd tennem). Másrészt, amit én akarok az nem feltétlenül szokványos, legalábbis a szűrők felhasználása szempontjából.

Tehát vannak neked ilyen szűrőid, többféle.
Minden szűrő egy osztály.

Vannak fv-eid, amikben ilyen szűrőket használsz. És szeretnéd néha újrainicializálni benne a szűrőidet.

Jól értem?

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

Nem feltétlenül önálló osztály minden szűrő. Inkább önálló példányok egy osztályból (az egyszerűség kedvéért).

De egyébként jól érted.

Arra gondoltam én is hogy van többféle szűrőd, és minden fv-ed használ pár sajátot (statikusan) ezekből.

Tehát most ilyened van:

void func1(...)
{
   static Filter1 filter1;
...
   //impl
}
...
for(...){
   for(...){
     ...
     func1(...);
     ...
   }
   //reset
}

Ehelyett legyenek a fv-ek objektumok. Ha funktort csinálsz belőlük, akkor alig kell változtatnod a kódodon:

class Func1
{
public:
   void operator() (...)
   {
      //impl
   }

private:
   Filter1 filter1;
   ...
};

...
for(...){
   Func1 func1;
   for(...){
     ...
     func1(...);
     ...
   }
}

És kész. A belső ciklushoz hozzá se nyúltál, a fv-ek átírása is szinte triviális.

Vagy:

class Func1
{
public:
   void operator() (...)
   {
      //impl
   }

   void reset()
   {
      //reset
   }

private:   
   Filter1 filter1;
   ...
};

static Func1 func1;

...
for(...){
   for(...){
     ...
     func1(...);
     ...
   }
   func1.reset();
}

Ennek az utóbbinak megvan az az előnye, hogy tényleg ugyanúgy használod a funktorokat mintha fv-ek lennének.
(És megvan az a hátránya ami egy statikus objektumnak általában: különböző fordítási egységekben található statikus objektumok inicializációjának sorrendje nem definiált.)

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

De most ebben az esetben, ha funktorokat hasznal, az nem olyan, mintha megeroszakolna az OOP-t?

Ha úgy jobban tetszik, ezeket a képződményeket ne hívjuk funktornak. Csak osztályok amiknek véletlenül pont van egy operator() fv-e.
Ha így nézed ez teljesen ugyanaz, mint amit te írtál feljebb, csak így talán kevesebb kódot kell átírni...

A statikus példányok szépségén lehet vitatkozni, de én csak annyi mondok: cout.

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

Valójában nálam sem függvénnyel, hanem osztállyal van megvalósítva, majdnem pont úgy ahogy a példádban írtad.

A probléma az, hogy nem tehetem a példányok létrehozását a belső cikluson (pontosabban az abban meghívódó "nagy" függvényen) kívülre a már részletezett okok miatt.
Ahogy most kinéz, az marad, hogy a legfelső szintű interfészen keresztül kell rángatnom egy reset flaget.

Jaj, de most döntsd el, hogy C programot, vagy C++ programot írsz. :)

hát, elvileg C++ lenne :)

Kis adalék a helyzet megértéséhez:

A belső ciklusban lévő dolgoknak "önhordónak" kell lenniük, mert a végső rendeltetésük nem abban a ciklusban futni, hanem egy dll-be (vagy más, dinamikusan linkelődő könyvtárba) lesznek fordítva. Ezért nem tehetek semmi olyat rajtuk kívülre, amire egyébként szükségük van.

Mivel ez ilyen cross-compiling-féle dolog, tehát a target az egyáltalán nem az a vas, amin fejlesztek, ezért a ciklusok, meg minden ami a belső ciklus magján (pontosabban az ott meghívott "nagy" függvényen) kívül van, az "csak" egyfajta tesztkörnyezet-féle. Ráadásul, erre az egész resetelős dologra csak itt van szükség, a targetre fordítva már nincs.

Ezekből következik, hogy lennie kell egy olyan interfésznek, ami csak szabványos függvényargumentumok átadására szolgál, ami mentén kettéválasztható a kód. Ezért nem lehet semmilyen globális változóval (ill. példányokkal) meg egyéb globális trükkel próbálkozni.

Amúgy most arra hajlok, hogy mégis megpróbálom valahogy globális változókkal, de az összes hacket feltételes fordítási makróba teszem, hogy a targetre ne forduljon be.

Akkor meg csinálj valami ilyet:
http://hup.pastebin.com/f4ac2a3de

Ez lesz neked a szép megoldás, főleg ha egy univerzális lib -et akarsz csinálni.
(Ha tényleg univerzális lib lesz, ne felejtsd el a megfelelő hívási konvenciót beállítani, az import headerben is, különben lehetnek egy-egy rendszeren meglepetések, pláne ha mondjuk nem C-ből, hanem valami más nyelvből akarják majd használni a libedet...)

Egyébként nézz rá a zlib -re, nagoyn ötletes, ahogy ott van ez megvalósítva.
gyakorlatilag az inflate()/deflate() függvények, amik a tömörtést/kitömörtést végzik, csak egy ilyesmi struct -ra mutató pointert kérnek paraméterül, és a programnak a stuct erre kijelölt mezőiben jelzik, ha a bemeneti buffer kifogyott, vagy a kimeneti buffer megtelt, ekkor a program beolvas adatokat, vagy kiírja azokat, etc.etc.

Ha nem gányolást akarsz, és tényleg rendes lib -et akarsz, akkor feltétlen ilyesmiben gondolkozz.

Aztán később csinálsz a libedhez egy C++ interfacet, ami egy wrapper class lesz csak.

Ezt nem igazán szeretném, mert a kérdéses változókat így is függvényen kívül kell kezelni (struktúra). Valamivel egyszerűbbnek érzem, ha belülre teszem a resetet de csak feltételesen beforduló formában.

De nem tudom igazán, még gondolkoznom kell a példádon.

Nézd, úgy csinálod, ahogy akarod, mi itt felvázoltunk neked többféle megoldást.
Remélem, tudtam valamit segíteni!

Igen, tudtál, és a többieknek is köszönöm.

A legfontosabb hozadéka az volt a beszélgetésnek, hogy kiderült, hogy valószínűleg nem lehet úgy megoldani, ahogy eredetileg akartam. Ez sok időt megspórolt nekem, mert képes lettem volna napokig pörögni rajta, feleslegesen.

A hogyan tovább már egy másik kérdés, azt még nem tudom pontosan.

Es itt erkezett el az a pont, amikor jobban tudnank segiteni, ha nem csak kodos nagy titokzatos feladatrol beszelgetnenk, hanem valami, a fentinel konkretabb kodot is kapnank. Szerintem baromira elbeszelunk egymas mellett. Eddig nekem is ugy tunik, hogy a feladatra tervezett koncepcio az, ami el lett baltazva, es te most kinlodsz az elbaltazott koncepcio menten szuletett koddal.

Ha a cel a C kompatibilitas, azt barmikor ki lehet valtani wrapper fuggvenyek letrehozasaval, szoval ettol ne tarts.
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

Le vagy maradva, már meghekkelte a saját programját. ;)

Én nem látom a lényegi különbséget aközött, hogy külön-külön minden változó statikus, és aközött, hogy egy osztályba vannak összefogva, és az egész objektum statikus.

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

Igen, ezért is írtam, hogy ebből a szempontból a probléma ugyanaz.

Ez oké, csak mi nem azért pofázunk itten osztályokról, hogy azokat csináld meg statikusra, hanem azért, hogy egyáltalán ne használj statikus változókat...

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

De kell, sajnos, nem jókedvemben használom őket.

Itt többen vagyunk akik úgy gondoljuk, hogy elkerülhető lenne a statikus változók ilyen mértékű használata némi refactoring munkával.

Mivel te ezt nem akarod meglépni, ebből következik, hogy de, jókedvedben használod őket... :)

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

Nem akarom meglépni, persze. De ha máshogy nem megy akkor meg fogom.

thread safe fuggvenyben nincs static valtozo. Sem osztaly, sem osztalyvaltozo sem sem.

Ha semaforozzák/mutexezik, akár még lehet is.... :) :)

+1, valoszinuleg nem lett rendesen megtervezve ; De sosem keso kijavitani :)
==
`Have some wine,' the March Hare said in an encouraging tone.
Alice looked all round the table, but there was nothing on it but tea.

"valoszinuleg nem lett rendesen megtervezve"

hát ez sajnos így van :)

vegigolvastam az egesz topicot.
Megbecsultem a programozoi tudasodat, es a programjaid bonyolultsagat.

Azt hiszem, neked a longjump() fuggvenyt kellen hasznalnod, olyan modon,
hogy a fuggvenyedben a static valtozo deklaralasa utan longjumppal elugrassz egy masik fuggvenybe, ott egy masik (globalis) valtozobol megtudod, hogy inizni kell-e a fuggveny static valtozojat vagy sem, es ezt megcsinalod, majd longjump() -pal visszaugrani az eredeti fuggvenybe.

Ez az egytlen megoldas, hogy meg idejeben teljesen menedzselhetetlen legyen a kodod, es kenytelen legyel kidobni es ujrairni az egeszet, mielott meg 2 ev munkat belefeccolsz.

happy hacking:-)

"vegigolvastam az egesz topicot.
Megbecsultem a programozoi tudasodat, es a programjaid bonyolultsagat."

Huhhh, hát ezt nagyon köszönöm, ritkaság, mert manapság nem szokás olvasni, csak írni :)

Nem egészen értem, hogy miért lenne jó nekem az ugrálás.

Most leginkább arra hajlok, hogy egy globális változóban kezelem az initflaget, de a függvény(ek)en belül a lekezelését makrón belülre teszem, úgy, hogy nem fog befordulni, ha a targetre fordítok.

Az ugralas arra jo, hogy az egesz projekten nyomj egy rm -rf -et duhodben, es vegre elkezdj ertelmes kodot irni. Vagy legalabbis ertelmes kerdeseket.

Ezt imadom, van egy kelloen kurvabonyolult problema, es akkor jonnek az altalanos peldaikkal, amire kapnak altalanos valaszt, majd kozlik, hogy a valasz neki nem jo, az egesz ugy ennel sokkal bonyolultabb. Hat ha bonyolultabb, akkor miert nem bonyolultabban kerdez?! Hatha akkor a valaszadok ugy 80%-a nem toszna el a sajat idejet azzal, hogy megprobalja rejtelyes kodositesekbol megfejteni egyfelol a kod kornyezetet, masfelol a kod celjait.
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

De goto -zzon egyet-kettőt a függvényen belül is, úgy a tuti. :)

Az igazi programozó nem fél a GOTO-tól :)

Látom, te az vagy, mert C++ -ban is tudsz FORTRAN programot írni. :D :D

-nagyon rég volt már hogy ilyesmibe botlottam
-commenteket sem olvastam végig mert alig látok ki a fejemből
-veszélyes ez a módszer

hozz létre egy pointert a függvényen kívűl, és egy a pointerre mutató pointert adj át a függvénynek,
majd a függvényen belül irányítsd az eredeti pointert a statikus változó címére,
miután kilépett a függvény a pointeren keresztül változtasd a változód értékét

(egyáltalán nem vagyok benne biztos hogy ez működőképes ebben a formában de egy próbát megér, sry hogy nem tesztelem de ko)

glhf

Nem jó, de ez csak a hozzászólásokból derül ki, hogy miért nem, most nem írnám le n+1.-szerre, de azért kösz.

Egyébként úgy néz ki, hogy sikerül megoldanom.

Óriási mázlim van úgytűnik, proof-of-concept szinten már működik is a dolog :)

Az lett a nyerő, hogy csak az elkülönítendő függvényt tartalmazó fodítási egységbe kellett beszenvedni globális változós trükkel az init flaget, ez azt jelenti, hogy csak ezen a szinten kellett makrózni.
Utána az osztályokban egy, a működés sajátosságait kihasználó trükkel viszonylag fájdalommentesen sikerült alaphelyzetbe állítnai az állapotváltozókat.

Hekkmester! :P

Jezusom... ezert psc es tr3w tuti elve fognak kibelezni. Elore is reszvetem. Ja, es nagyon boldog karbantartast.
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

Miert beleznenk, ki, az o programja, azt csinal amit akar.
Amig nem az en sajat forraskodjaimban kovet el ilyeneket, addig az o dolga... ;)

Engem sem zavar, amíg nem nekem kell takarítani utána. :)

Mondjuk ilyen után ne lepődjön meg senki, ha meglátja a kódját a Daily WTF-en. :)

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

Szerintem az a változó, amelyik csak a függvényen belül tartja az értékét, az pont a nem-statikus változó. Ha fontos, hogy ez a változó, egy külső statikus értéket vegyen alapul, akkor passzold a függvénynek az értéket. Vissza is lehet return-ölni - de akkor nem void lesz a függvényed.

Vagy nem értem pontosan a problémát.

"Jegyezze fel a vádhoz - utasította Metcalf őrnagy a tizedest, aki tudott gyorsírni. - Tiszteletlenül beszélt a feljebbvalójával, amikor nem pofázott közbe."

kevered a statikus es a globalis valtozo fogalmat.