Fórum Root.cz
Hlavní témata => Vývoj => Téma založeno: Ondřej Novák 28. 09. 2017, 13:31:26
-
Narazil jsem na následující problém. Mám tento kód
std::fstream out(fname.c_str(),std::ios::out|std::ios::ate);
když ale pustím strace, vidím následující:
open("./backup-1506250110-btcusd-orders.json", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 4
lseek(4, 0, SEEK_END) = 0
lseek(4, 0, SEEK_CUR) = 0
Tušíte někdo, proč tam je to O_TRUNC následované zbytečným seekem na konec? Mám to hlásit jako bug, nebo je to WAI?
gcc version 6.2.0 20161005 (Ubuntu 6.2.0-5ubuntu12)
PS: nemůže být problém v tom, že bych koukal na jiný řádek v programu, jelikož je to jediný místo, kdy se tento konkrétní soubor otevírá. Taky jsem před testem udělal full rebuild
-
Myslim, ze kdyz chces pridavat tak ios::app. Out zacina s praznym souborem.
-
Ten seek je tam proto, že se soubor otevírá s ios::ate. To je jediný, co ios::ate dělá, po otevření souboru seekne na konec.
O_TRUNC je v parametrech fce open kvůli kombinaci ios flagů, jestli nechceš O_TRUNC, tak buď soubor otevři s ios::app nebo s ios::in | ios::out.
ios::app seekne na konec souboru před každým zápisem (open s O_APPEND). seek + write je v tomto případě atomická operace, takže jestli chceš psát na jiné místo než na konec a nechceš O_TRUNC, nemůžes použít ios::app, ale musíš soubor otevřít s ios::in | ios::out. To soubor otevře s O_RDWR (žádný O_TRUNC, ale ani O_CREAT, tak si soubor popř. musíš vytvořit sám). A jestli do flagů přidáš ios::ate nebo po otevření zavoláš out.seekp(0, ios::end) není prakticky žádný rozdíl.
Tady máš něco k tomu, jak se z ios flagů určí file mode http://cpp14.centaur.ath.cx/filebuf.members.html (http://cpp14.centaur.ath.cx/filebuf.members.html)
-
ios::app funguje. Vlastně původně jsem si myslel, že fungovat nebude, protože to používám k detekci toho, zda soubor už existuje nebo ne (C++neumi O_EXCL). Pokud mi tellp vrátí nenulový výsledek, tak vyhodím výjimku. Přišlo mi, že v režimu app nemůže tellp fungovat, protože to víc funguje jak stream.
Co vlastně dělá ios::trunc.... mě tedy nedělá nic, protože samotné ios::out udělá automaticky trunc. Doteď jsem ho všude uváděl, ale koukám, že naprosto zbytečně.
Jen tak si všimněte, že v strace není použit příkaz O_CLOEXEC. Dnešního hlediska bezpečnostní nutnost. (STL je vlastně nebezpečná)