[MEGOLDVA] wine alatt windows c programban az fflush nem megy

Fórumok

Sziasztok!

Kicsit részletesebben a tárgyban leírtak:

Van egy 3D Gamestudio nevű windows-os fejlesztő környezet amit wine-ban futtatok. Ebben készítek egy házikedvenc programot. A környezetben a Lite-C nyelvet lehet használni. Ez a program nyelve.

A programban van egy rész ami log fájlt készít és az fflush funkciót használja arra az esetre, ha elszállna az alkalmazás, de még volna kiírandó sor a log-ba.

A rendszer (wine + 3D GS) jól működött amíg egyszer a system update (volt ott minden mint a búcsúban) után bemondta az unalmast és végtelen ciklusba került/lefagyott. A debug során kiderült, hogy az fflush hívásán akad el.

Ebben szeretnék segítséget kapni, hogyan lehetne felülkeredni a problémán. Próbáltam downgrade-t, meg 64 bites helyett 32 bites prefixet használni, különféle library-ket felrakni. Egyik sem segített, bár lehet nem a megfelelővel próbálkoztam. Az fflush egyébként az msvcrt.dll-ben található, ha ez számít.

Az OS amit használok Manjaro 24.0.4 Wynsdey, Kernel: x86_64 Linux 6.9.9-1-MANJARO.
wine verzióL: 9.12

Előre is köszönet mindenkinek aki segíteni próbál.

Hozzászólások

>volt ott minden mint a búcsúban

A 3D GameStudio vagy a wine+Linux volt frissítve? Mi volt a búcsúban, össze kellene szedni, ha lehet.

> fflush

Szerintem jelentős esélye van, hogy teljesen máshol van a hiba, és memória korrupció, vagy hasonló az eredeti ok. Bár a wine réteg miatt lehet hiba az fflush-ban is valóban. De ezt verzió visszalépés biztosan orvosolná, ha tudod, hogy milyen verzióról indultál el, és oda térnél vissza.

Mindez már több hete történt ezért az emlékeim egy része nem megbízható.
De, ami biztos, hogy 3D GS nem volt frissítve (kb. 10 éve jött ki az utolsó update).
Az is biztos, hogy a wine + Linux frissítve volt. Sőt, azóta újratelepítettem a gépet, tehát méginkább frissebb lett.
Ami nem biztos de lehetséges, talán nem 9-es volt a wine fő verziószáma, hanem 8. Ismétlem, nem biztos.

Lehet, hogy teljesen máshol van a hiba. Viszont az fflush hívásánál jelentkezik.
Kétszer próbáltam wine downgrade-et. a 9.9-re és a 9.8-ra. Talán még többet kellett volna visszalépnem, de elbizonytalanodtam mivel már régebben történt, ahogy már írtam.

A memória korrupcióhoz megjegyezném, hogy próbaképpen írtam egy 8-10 soros programot. A jelenség ugyanúgy megismétlődik. Kérésre ide tudom tenni a forráskódot.
Tehát szerintem nem memória gond.

Még nincs aláírásom.

Akkor itt van a kód, hát 28 sor, de gondolom nem ez számít.
Most szúrok be itt először kódot, elnézést ha elsőre nem sikerül.
A behúzás valamiért nem szeret átmenni... A forráskód gomb pedig makacsul másképpen működik mint ahogy szeretném.

/*
    fflush proba (3D Gamestudio Lite-C)
*/

#include <strio.c>

#include <windows.h>
#include <stdio.h>
#include <d3d9.h>

function main() {
    var fhandle_n = 0;

    level_load(NULL);
    wait(2);

    fhandle_n = file_open_write ("bubu.txt");
diag_var("\nfhandle_n: %6.3f",fhandle_n);

    file_str_write(fhandle_n, "bubu\n\r");
diag("\njon");
diag_var("\nfhandle_n: %6.3f",fhandle_n);
    fflush(fhandle_n);        // itt akad el...
diag("\nmegy");

    file_close(fhandle_n);
}

Még nincs aláírásom.

Nem biztos, de szerintem mingw-gcc nem ismeri a lite-c nyelvet.

A 3D GS kipróbálás elvileg nem nehéz, letöltés kb. 1 perc. Install kb. másik perc. Van teljesen ingyenes változat.
Akinek kedve van hozzá, itt van a telepítő exe: http://server.conitec.net/down/gstudio8_setup.exe

Még nincs aláírásom.

Van egy SED.exe a telepített környezetben. Az a gyárilag adott editor, persze más is használható.

A SED előnye, hogy képes annyira on the fly fordítani, hogy a binárist nem is gyártja le, hanem rögtön futtatja neked, mintha script lenne egy interpreterben.
Debug van, de csak globális változókra lehet watcher-t akasztani, a soronkénti lépkedés viszont jól működik, ha az kell. Ja, és a debug is megy interpreter módban.

Egyébként a lite-c nem változott kb. 10 éve. Ez alapján kevésbé gyanakodnék arra.

Még nincs aláírásom.

Ha gdb-vel vagy valami debuggerrel megfigyelhetővé teszed, hogy mi történik (legalább a disassemblyn lehet lépkedni), akkor van szerintem némi esélyed rájönni, hogy mi a hiba oka. Ha van egy köztes ábrázolása a kódnak (ASM, vagy C vagy ilyesmi), akkor abból is ki lehtet indulni. Anélkül szerintem esélytelen, mert nem tudjuk, hogy odabenn mit kavar a Lite-C.

Egy alternatív megközelítés: kezdd el elvenni a kódból azt ami nem ide tartozik és figyeld meg, hogy melyiknél javul meg: az okozza a korrupt állapotot - feltéve, hogy korrupt állapot a baj forrása. Ha a fflush maga rossz lenne, akkor elég lenne kinyitni a fájlt beleírni és fflusht hívni, a többit ki is lehetne törölni, mert az csak zaj lenne.

A gdb-vel illetve annak használatával 3D GS kapcsán annyira kevés ismeretem van, hogy ilyesmire nem tudok vállalkozni.

Az alternatív megközelítés megtörtént az itt közölt forráskódban (tudod... a 28 soros). Amennyiben kikommentezem az fflush hívásának sorát, jól működik.
Amikor ezt visszacsinálom végtelen ciklus vagy fagyás vagy mit tudom én micsoda történik.

Még nincs aláírásom.

Tehát egy darabig minden oké volt, aztán egyszer felborult a rendszert, és attól kezdve minden alkalommal lefagy? fsck lenne az első ötletem.

A lefagyás csak annál az 1 programnál jelentkezik. Nem az oprációs rendszer fagy.

Egy korábbi válaszomban írtam, hogy újratelepítettem a komplett rendszert. Így is az fsck lenne a javaslat? Nem tagadom én is gondoltam rá, csak úgy gondoltam, hogy nem az a megoldás.
Megcsinálom, csak jól jönne egy arra is egy javaslat, hogyan nézzen ki a parancs. (kb. 15 éve futtattam fsck-t, azóta a memóriám kicsit megkopott)

Még nincs aláírásom.

Szerkesztve: 2024. 07. 23., k – 15:18

A probléma egész biztosan a Lite-C runtime libjében gyökerezik.

Az fflush egyébként az msvcrt.dll-ben található, ha ez számít.

Egész biztos nem. Az az fflush, amit Te használsz a Lite-C kódodból, és az az fflush, ami az msvcrt.dll-ben található, nem lehet azonos. Vagy ha mégis, akkor pont az a gond.

Ugyanis nálad a "fhandle_n" típusa "var" (akármi legyen is az), míg az msvcrt.dll beli fflush "FILE*" típusú mutatót vár. Szerintem nézd meg, hogy van-e a Lite-C runtime libjében valami "file_flush" vagy hasonló nevű függvény, és használd azt. Szerintem ennek a wrappernek lenne a feladata, hogy a "var"-odat átkonvertálja "FILE*"-é és úgy átadja az igazi fflush-nak, hasonlóan a "file_open_write"-hoz.

Vagy, ha ez a Lite-C simán engedi az msvcrt.dll függvényeinek hívását, akkor cseréld le a "file_open_write" hívást "fopen"-re, "file_str_write"-t "fprintf"-re, stb. és a "fhandle_n" legyen "FILE*" típusú.

Mindenesetre ha ez a "var" típus egy int-et takar, mint ahogy sejtem, akkor tök egyértelmű, hogy azt pointerként átadva a fflush-nak fagyás az eredmény.

A méréseim (igaz, nem Wine, csak Windows11) ezt teljesen alátámasztják: ezek a függvények inkompatibilisek.
Részletek itt:
https://github.com/lzsiga/hello-world/commit/6e74e610852af4b7df9adee6ce…

Szerk: emlékeztetőül beidézném a programozás alaptételeit:
1. Minden programban van hiba.
2. Az első tétel a hiba kijavítása után is igaz marad.
3. A látszólag helyes működés nem bizonyít semmit, csak azt, hogy nem manifesztálódik a hiba.

Szerkesztve: 2024. 07. 23., k – 15:49

Belenéztem az include könyvtárban található stdio.h header-be.
Az alábbi sorok hasonlítanak gyanúsan (esélyesek) arra amit használnék:

int __cdecl fflush(FILE *);
...
API(fflush,msvcrt)

A windows.h is tartalmaz flush-re utaló sorokat, de egyelőre talán ez is elég.

Egyébként, attól, hogy a típus var, még lehet FILE-ként használni. Szerintem...
Láttunk már ilyent. Pl. cast vagy ilyesmi kapcsán.

Még nincs aláírásom.

Egyébként, attól, hogy a típus var, még lehet FILE-ként használni. Szerintem...

Csakis abban az egyetlen egy esetben, ha a "var" valójában egy FILE struct memóriabeli címét tartalmazza. Minden más esetben, ha nem egy FILE struct címe csak egy random cím, vagy egyáltalán nem is cím, hanem egy sima szám (ami egyébként a jellemző, pl az "open"/"read"/"write"/"close" egy számot vár), akkor garantált a fagyás.

Mivel ez a Lite-C elrejti előlünk, hogy a "var" valójában mi, ezért nem lehetünk biztosak; de abból kiindulva, hogy számként (ráadásul float-nak castolva) simán ki tudta írni, gyanítom, nem mutató lesz az. Egy normális C fordító besír ugyanis, ha mutatót próbálsz float-nak castolni, míg az int float konverzió implicit és automatikus szokott lenni. De csak tipp, nem ismerem ezt a Lite-C-t.

Ez simán lehet a frissítés miatt. Ha az az fflush valóban a dll-beli, akkor az azt jelenti, egy nem érvényes FILE címet atdsz át neki, tehát UB-d van.

Simán el tudom képzelni, hogy a korábbi wine esetén az emulált fflush (vagy ha nem built-in az msvcrt.dll hanem native, akkor az általa hívott emulált dll-ek valamelyike) csendben elhasalt, azaz érvénytelen bemenetre nem történt igazából semmi és csak visszatért.

Ugyanakkor a frissítést követően (vagy az új built-in fflush vagy ha native akkor az általa hívott emulált dll-ek valamelyike) már nem szereti az érvénytelen bemenetet, és ez fagyást eredményez.

Az is lehet, hogy a frissítést követően a Lite-C runtimeban megváltozott valami (frissített dll függőség miatt), és habár eddig olyan "var"-t adott vissza a "file_open_write", ami FILE mutatóként nem okozott galibát (mondjuk egy használaton kívüli veremrészre mutatott, pl a red-zone-ra), addig a frissítés után már egy olyan "var" értéket ad vissza, ami mutatóként már nem használható (mundjuk pont egy nem belapozott memóriaterület címe van benne).

Csak egy példa: tegyük fel, hogy "var" egy int szám, a megnyitott fájlok indexe. A frissítés előtt a "file_open_write" volt az első megnyitott fájl, tehát 0-ás indexszel tért vissza. Ezt átadva az fflush-nak az NULL-ra castolódott, és az fflush(NULL) paraméterrel minden megnyitott fájlra vonatkozik. A frissítést követően valamelyik dll talán megnyitott már egy fájlt még a Lite-C-d előtt (vagy duplikálta az stdout-ot vagy ilyesmi). Így a "file_open_write" által megnyitott fájl indexe az 1 lett. Ezt castolva FILE*-ra és átadva a fflush-nak az megpróbál olvasni az 1-es memóriaoffszetről, ami garantáltan fagyás.

A FILE* pointer akkor van feltöltve amikor a fájlt megnyitom. A mutató korrekt mivel ha fflush nélkül zárom le a fájlt - és itt is a mutatóval van parameterezve a close - , az jól működik.
Ezért szerintem a pointer egy érvényes jó címet tartalmaz.
Így szerintem az egész eszmefuttatás valahogy érvényét veszti.

Nem tudom mi az a frissített dll függőség, de én is a dll-re gyanakszom (msvcrt).

Hogy a bátorságot is felvegyük a programozói erények közé, a wine downgrade-del elmegyek egészen régi verziókig. Mondjuk a 8-as főverziószámmal, mivel emlékeim szerint az működő állapot volt.
Persze, egyáltalán nem biztos, hogy ez sikerre visz. Minden esetre megpróbálom és itt adok visszajelzést az eredményről.

Még nincs aláírásom.

Ezért szerintem a pointer egy érvényes jó címet tartalmaz.

Nem, még csak az sem biztos, hogy pointer-e egyáltalán. A lezárás azért működik, mert arra nem a "fclose"-t használod, hanem a "file_close"-t, ami a "file_open_write" párja. Ez utóbbi kettő egyaránt "var" típusú változót ad vissza és vár paraméterül, és nem is az msvcrt.dll-ben találhatók, hanem a Lite-C runtime-ban.

Alapvetően az a baj, az okozza az UB-dat, hogy kevered az interfészeket.

1. vagy használj "file_flush"-t "fflush" helyett,
2. vagy használj "fopen"-t, "fclose"-t "file_open_write" és "file_close" helyett, de ne keverd.

Esetleg használj direktben "fflush(NULL)"-t, az minden írásra megnyitott fájlt flush-ol, függetlenül attól, hogy "fopen"-el vagy "file_open_write"-el nyitottad-e meg (nem hiszem, hogy túl sok írásra megnyitott fájlod lenne, szóval nem para).

1. Sajna "file_flush"-t nem találtam a gyári include fájlokban. A fordító szerint sincs: "'file_flush' undeclared identifier"
2. Természetesen használhatom a natív c függvényeket (máshol a programban meg is teszem), de. De nekem kell az a flush bárhogyan is nevezzük. Esetleg a natív flush talán jó lesz?

Az a NULL paraméteres hívás érdekes. Ezzel kapcsolatban még írok itt.

Szóval. Bátran visszaléptem a wine 7.22-es verziójára és valami függőségi baja volt. Jó.
Léptem egyet odébb, a 8.1-1 verzióra. Csodák csodájára pöccre indult. Úgy értem, jól működött a program (a példaprogram) elejétől végéig.
És itt jön a NULL, azzal is ment. Tehát az egy pozitív ötlet volt. Köszönöm, eszembe se jutott volna.

Most még annyi, hogy lépegetek egy néhány verzióval feljebb, hátha kiderül, hol "romlik el". Mert ugye szerinted lehetséges, hogy a wine kezdett el jól működni az újabb verziókban ami betett a GS-ben használt fflush-nek. Ezt a variációt én is hihetőnek gondolom.

Még nincs aláírásom.

Sajna "file_flush"-t nem találtam a gyári include fájlokban

Ez esetben marad a javaslatom második fele: "var" helyett legyen "FILE*", "file_open" stb. helyett "fopen" stb., és úgy biztos menni fog.

Az a NULL paraméteres hívás érdekes. Ezzel kapcsolatban még írok itt.

Ezt működőképes kerülőmegoldásnak nevezném. Egy próbát mindenképp megér, ha nem akarod nagyon átírni a már meglévő kódot.

Annyi itt a segítőprogram, hogy az ésszerű megoldás a 'flush' kicserélése 'close'+'open'-re. Illetve, ha a 'close' előtt van, akkor simán kihagyható.

És a nemhasználata a megoldás.

Ez a Lite-C nagyszerű dolog lehet, de ez 'var' típus konkrétan hazavágja az egészet, nincs semmilyen ellenőrzési lehetőség arra (lásd bzt kolléga hozzászólását), hogy a `flush` használható-e ilyen kontextusban, vagy valami mást kellene keresni.

Egy biztos: ha a `close` nem hajt végre automatikusan puffer-ürítést, akkor úgyis reménytelen az egész, szóval bátran tegyük fel, hogy a `close` előtt nem kell `flush`, ahol meg kell, ott a `close`+`open` használható helyette. (Igaz, hogy általános esetben lassabb, de a te konkrét esetedben gyorsabb.)

Szerk: ha szemét lennék, most felemlegetném az `fsync` nevű mágiát is.

Mi van akkor a te forgatókönyvedben arra az esetre, ha nem ér el a program végrehajtása a close hívásáig?
Tegyük fel, írás történt a log fájlba, de még pufferben van a sztring.
Megdöglik a program close hívás nélkül. Ebben az esetben hogyan éred el azt, hogy a log tartalmazza a pufferben lévő sztringet is?
Nálam az fflush volt a befutó. Nálad mi?

Minden jó megoldásra vevő vagyok.

Szerk: A write utáni close+open nemcsak hogy nem elegáns de nem is hatékony. Viszont lassú azt el kell ismerni.

Még nincs aláírásom.

Tippre ilyen esetben bitre ugyanaz történik, mint a te megoldásod esetén akkor, amikor a program megdöglik az fflush() hívás előtt.

Mivel a javaslat az volt, hogy a fflush() helyett legyen egy close()+open() páros, ezért ha az adott pontig eljut a program, akkor akár a fflush(), akár a close() kiírja a cache tartalmát, ha idáig se jut el, akkor meg tök mindegy, melyik hívás nem üríti.
Egyébként nekem dereng olyan ioctl() hívás, amely tiltja a cache használatát - de ez nagyon régi és alapvetően Linux alatti kódból felderengő ködkép.

Szerkesztve: 2024. 07. 23., k – 19:08

Szóval.....

A következő wine verziókkal próbáltam:

8.1   működik
8.4   működik
8.8   nem működik
8.11 nem működik
9.6   nem működik
9.8   nem működik
9.11 nem működik
9.12 nem működik

Meg kell jegyeznem, hogy módosítanom kellett a kódon mert invalid pointer hibát jelzett, ahogy azt bzt is peddzegette. (ezt 2 d-vel írni?)
Itt van a módosított kód, csak a main tartalma:

function main() {
    var fhandle_n = 0;
    var xhandle_n = 0;

    level_load(NULL);
    wait(2);

    fhandle_n = file_open_write ("bubu.txt");
    xhandle_n = fhandle_n;
diag_var("\nfhandle_n: %6.3f",fhandle_n);

    file_str_write(fhandle_n, "bubu\n\r");
diag("\njon");
diag_var("\nfhandle_n: %6.3f",fhandle_n);
    fflush(xhandle_n);        // itt akad el...
diag("\nmegy");

    file_close(fhandle_n);
}

Mint látható az eredeti handle mentésére volt szükség és annak használatára az fflush-ben. Mert az kinullázta.
Továbbra is nyitott vagyok minden hozzászólásra, megjegyzésre.

Attól még megoldottnak fogom tekinteni mostantól a témát.

Üdv és köszönet mégegyszer mindenkinek.
p.s.
azt nem tudom ezt hogyan kell a téma címébe beleírni.
p.s.2
rájöttem :)

Még nincs aláírásom.

Képzeljétek fejlemény történt!

A winehq.org oldalán valaki példaprogramot kért tőlem, talán az eset kivizsgálására (mi másra).

Igazából blog-ba kellett volna írnom ezt? Vagy az egészet a probléma felvetéssel együtt? Még új vagyok itt és kicsit tanácstalan.

Még nincs aláírásom.

Pillanat. Wine alatt Windows 11-ben vagy csak simán wine nélkül Windows 11-ben? (Számomra kicsit félreérthető, elnézést)

Még nincs aláírásom.

Tegyük félre a Wine-t: a fflush hívása ebben a kontextusban hiba, aminek a bemutatásához nem kell Wine, mert natív Windows alatt is jelentkezik.

Azt valóban lehet nyomozni, hogy milyen körülmények egybeesése miatt nem manifesztálódott a hiba egyes Wine-verziókban.

A manifesztációhoz annyit tennék hozzá, hogy amikor a GS-t még fejlesztették, vagy inkább karbantartották, még nem létezett Windows 11. Talán még Windows 8 sem (ez nem biztos).
Nagyjából 2010 környékén adták ki az utolsó update-t. Elnézést, ha rosszul emlékszem.

Ami biztos, hogy a rendszer a Windows 7-ben való futásra volt fel- illetve elkészítve. Ez azért fontos lehet a manifesztáció szempontjából.

Még nincs aláírásom.

Itt lehetne nézelődni:
https://github.com/wine-mirror/wine/blob/master/dlls/msvcrt/file.c 836. sorban kezdődik a msvcrt_flush_buffer
Vagy az általa hívott _write, vagy bármi, amit az hív.

Alapvetően az a gond, hogy a FILE *file paraméter nem egy FILE struktúrára mutat, hanem valamilyen gamestudio-specifikus adatterületre.

Szóval nyitottak egy hibajegyet a fórumbeli posztom alapján.

Elolvastam és nem értek teljesen egyet azzal amit Paul Gofman írt.
Mivel a régebbi verziókban nem random módon hol működött hol nem működött.
Hanem mindig működött. Megpróbálok a winehq oldalán is erre reflektálni, bár nem tudom milyen eredménnyel.

Még nincs aláírásom.

Megnézem és megírom az eredményt.

Jó volt a kérdés. Nem látszott AZONNAL az eredmény. A fájl tartalmának változása menet közben nem látszott.
Csak a program lefutása után jelent meg benne a kívánt tartalom. Bár lelképzelhető, hogy rossz módszert használtam.
Azt azért hozzá kell tennem, hogy amikor régen ezt teszteltem, fflush nélkül nem jelent(ek) meg az utolsónak beírt sor(ok).
Csak, hogy a kép teljes legyen.

Még nincs aláírásom.

Téged megzavar a megfigyelésben az, hogy a fflush() hívás után rövidesen zárod is a fájlt, majd vége is az egész vándorcirkusznak. A fflush()-t elsősorban arra használjuk, hogy olyankor írjuk le a fájl tartalmát, amikor még nem akarjuk lezárni a fájlt, csak le akarjuk már írni a diskre/streambe a cuccot. A helyes teszt úgy néz ki, hogy a fflush() után várakozol mondjuk egy billentyűnyomásra (vagy mondjuk 5 percnyi sleepet), és amikor bejön a prompt, a másik terminálban megnézed, hogy van-e a fájlnak tartalma (mert ezt csinálja a fflush()) mondjuk egy cat-tal vagy (Windowson) Total Commanderben F3-mal. Amennyiben van tartalma, akkor mondhatod, hogy a fflush() működött, de attól, mert nem fagy jégkockára a programod, még abszolút nem biztos, hogy működik is az a hívás.

Blog | @hron84

valahol egy üzemeltetőmaci most mérgesen toppant a lábával 

via @snq-

Hibás alapfeltételezéssel indítasz.

A dolog úgy indul, hogy a fájl nyitása megtörténik. Ez egy log fájl. Amíg a program végrehajtása oda nem jut, hogy lezárja, addig közben-közben beleíródik egy vagy több sor. Futhat a program két percig vagy akár huszonkét óráig. Amíg fut és nincs zárás, és van írás, addig a log nőttön-nő. A flush szerepe az, hogy ha közben elszállna a program, akkor a legutoljára kiírt sor is legyen benne a fájlban.

Tehát a flush hívása után nincs fájl zárás, hanem a következő kiírandó sorra várakozás van. Aztán majd egyszer valamikor a zárás is megtörténik.

Igyekeztem részletesen leírni a koncepciót és a működést. Kérdezz vissza amennyiben valami tisztázatlan maradt.

Természetesen, most már nincs flush, csak nyitás, írás, zárás.

Még nincs aláírásom.

>> Alapvetően az a gond, hogy a FILE *file paraméter nem egy FILE struktúrára mutat, hanem valamilyen gamestudio-specifikus adatterületre

mindegyik gamestudios file_open_*() függvény az msvcrt-vel teljesen megegyező FILE struktúrát ad vissza, a probléma az, hogy amikor az msvcrt-s fflush() flock()-ot hívna rá, nem találja a saját iob-jában a handlet, ezért egy crit_sec-t feltételez közvetlenül a FILE struct után (+0x20), és abba zutty belecímez

ha az acknex.dll-ben ki lenne ajánlva a _fflush()/_flush_nolock(), azt lehetne esetleg használni

probléma továbbá, hogy a lite-c megzavarodik a flush() paraméterezésénél (ha az fhandle_n "var típusú", a saját fflush() szignatúra leírójában (include/stdio.h-ban) pedig FILE* szerepel, akkor a generált kódban már a FILE*-ra mutató referenciát (FILE**) ad át), de ez kijátszható

Én nem látok így bele a Gamestudio belső dolgaiba, csak arra tudok hivatkozni, amit a ticketben írtak:

Here the engine executing the script calls msvcrt.fflush(pointer). msvcrt.fflush() assumes it is FILE structure but it is not. It is some internal engine's structure returned by file_open_write(), no msvcrt / else MS CRT functions are called to execute those other engine's function, the engine works with kernel32.CreateFile() etc. directly.

szerintem ez csak egy szerencsétlen megfogalmazás, de később helyesen leírja a valódi problémát: "it assumes CRITICAL_SECTION follows FILE structure"

debuggolva az enginet a scripttel, a kitöltött FILE mezőkkel problámát nem tapasztaltam (a fenti dupla ref kezelése után), a crit_sec viszont valóban nincs (nem lehet) ott

Kétség kívül a fordító illetve az acknex motor indokolatlanul sokszor és sok helyen használja a "var" típust. Nekem se tetszik.
Én arra tudok gondolni, hogy mivel a var és a pointer (esetünkben FILE*) azonos byte hosszúságot foglal ezért pusztán értelmezés kérdése, hogy mit látunk  bele.
És pont ezt csinálja a cast módszer. Csak hogy egy példát hozzak fel.

A belső működést én nem tudom olyan jól feltérképezni mint te, ezért a többi mondatra sajnos nem tudok reagálni.

Még nincs aláírásom.

>> Én arra tudok gondolni, hogy mivel a var és a pointer (esetünkben FILE*) azonos byte hosszúságot foglal ezért pusztán értelmezés kérdése, hogy mit látunk  bele.

igen, de a lite-c ebből:

var fhandle_n;
fflush(fhandle_n);

ezt generálja a háttérben (a fflush() általa ismert szignatúrája alapján):

fflush(&fhandle_n);

ami kevésbé szerencsés, mert a fflush() nem FILE**-t vár

egy ilyen workaround viszont működik:

var fhandle_n;
FILE * f = fhandle_n;
fflush(f);

Természetesen. Az open-close páros működik.

Azt vettem észre, hogy fflush annyira azért működik, ha korábban elmentem a mutatót, hogy lezajlik az írás és megjelenik a szöveg a fájlban.
Tehát a pointer jó helyre mutat, és maga az írás rendben van. Utána jön valami gixer. Azt hiszem ezt a jelenséget korábban nem jeleztem.

Gondolom, az eddigiekhez képest alaposabban kell vizsgálnom.

Még nincs aláírásom.

Szerkesztve: 2024. 07. 30., k – 23:01

Jobban megnézve ezt a file.c -t, úgy tűnik, hogy _MSVCR_VER < 140 esetén egyes fájloknak nem jut ilyen CriticalSession, nevezetesen azoknak, akik a MSVCRT__iob -ba kerülnek.

(Ennek valószínűleg nincs köze a jelen problémához, csak egy kis példa arra, hogy bár elsőre jó ötletnek tűnt, ez a struct _iobuf _iob[20] tömb, talán mégis jobb lett volna, ha nem így csinálják, vagy legalább a stdio.h-ba nem vezetik ki.)

További érdekesség: https://stackoverflow.com/questions/30412951/unresolved-external-symbol…

Látszik, hogy a MS tudósai is igyekeznek inkompatibilitani (bár a glibc verziózott szimbolumai kemény ellenfelek ám). De ahogy az olimpián mondják, nem is a győzelem a fontos, hanem a felhasználók megszivatása.