Problém s C++ : ios::ate

Problém s C++ : ios::ate
« kdy: 28. 09. 2017, 13:31:26 »
Narazil jsem na následující problém.  Mám tento kód

Kód: [Vybrat]
std::fstream out(fname.c_str(),std::ios::out|std::ios::ate);

když ale pustím strace, vidím následující:

Kód: [Vybrat]
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?

Kód: [Vybrat]
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
« Poslední změna: 02. 10. 2017, 10:06:01 od Petr Krčmář »


linuxak

Re:problém s C++ : ios::ate
« Odpověď #1 kdy: 28. 09. 2017, 14:24:24 »
Myslim, ze kdyz chces pridavat tak ios::app. Out zacina s praznym souborem.

orcus

Re:problém s C++ : ios::ate
« Odpověď #2 kdy: 28. 09. 2017, 16:31:15 »
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

Re:problém s C++ : ios::ate
« Odpověď #3 kdy: 28. 09. 2017, 16:55:08 »
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á)