Mám program v C++ a v main() odchatávám svoje výjimky. V catch bloku chci jen vypsat chybu a ukončit program.
Narazil jsem na zvlášní chování – pokud hlášku vypisuji na standardní výstup, nehlásí mi Valgrind žádné chyby: All heap blocks were freed -- no leaks are possible. Pokud ale chci chybu vypsat na chybový výstup, hlásí mi: still reachable: 5,120 bytes in 2 blocks
Jasně, program stejně končí, tak je to vlastně jedno, ale stejně bych na to rád přišel. Jediné, co měním, je cíl výstupu. Zde jsou příklady z catch bloku a příslušné hlášky z Valgrindu:
// wcout << e.getMessge().c_str() << endl; // valgrind: All heap blocks were freed -- no leaks are possible // wcerr << e.getMessge().c_str() << endl; // valgrind: still reachable: 5,120 bytes in 2 blocks fwprintf(stderr, L"Caught exception: %s\n", e.getMessge().c_str()); // valgrind: still reachable: 5,120 bytes in 2 blocks // fwprintf(stdout, L"Caught exception: %s\n", e.getMessge().c_str()); // valgrind: All heap blocks were freed -- no leaks are possible // wprintf( L"Caught exception: %s\n", e.getMessge().c_str()); // valgrind: All heap blocks were freed -- no leaks are possible
Chtěl bych tam mít tu odkomentovanou variantu, abych nezasíral standardní výstup chybovými hláškami.
P.S. Následně jsem zjistil, že to ani nesouvisí s výjimkami. Pokud kdekoli v programu zapíši něco na chybový výstup, Valgrind hlásí: still reachable…
Nakonec jsem to vyřešil pomocí fclose(stderr). Je tedy potřeba vždy chybový výstup explicitně zavírat, zatímco standardní výstup ne?
Ja do toho moc nevidím, ale vyzerá na bug v glibc, alebo nejakej inej knižnici.
Aké prepínače si použil na Valgrind?
Bez přepínačů, základní nastavení.
Zkoušel jsem napsat minimální program, kde bude jen ten fwprintf() a tam se mi to nepodařilo nasimulovat.
V tom mém programu chyba zmizí, když přepíšu fwprintf(stderr, L"…\n") na fwprintf(stdout, L"…\n") nebo přidám fclose(stderr). S výjimkami to nakonec nesouvisí a s těmito konkrétními funkcemi taky ne, protože stejný rozdíl byl i mezi wcout a wcerr.
Zkusím si s tím ještě pohrát a kdych na něco přišel, tak dám vědět.
asi to bude tym ze cerr je nebufferovany a cout pouziva buffer. Pre detailnejsi rozbor chyby by bolo dobre vidno aspon kus kodu. vyhnut memory leakom sa mozes pouzivanim smart pointrov. Inak valgrind obcas hlasi aj false positive memory leaky.
Ad „cerr je nebufferovany a cout pouziva buffer“
Na to už jsem taky přišel, když jsem na to koukal přes strace :-)
Jinak ukazatele tam ani nepoužívám…
Už toto by stálo za nahlásenie bugu, pretože to bug je, keď sa výstup chová nepredvídateľne.
Asi by trebalo sa pozrieť do dokumentácie Valgrind a skúsiť nejaké agresívnejšie prepínače pre viac výstupu, na začiatok napr:
--leak-check=full --show-reachable=yes
Ten výstup sa chová predvídateľne. Funkcia cout je naviazaná na cin, a spláchne sa pri čítaní. Funkcia cerr má nastavený príznak unitbuf, a preto sa spláchne pri každom dovolaní operátora << .
Bug je, ak to nevieš a tak máš predstavu založenú na fantázii a nie faktoch.
cerr je unbuffered aby boli chybové hlášky zobrazené aj napriek tomu, že program na nasledujúcom riadku havaroval. S bufferom by sa hláška mohla stratiť.
Nie je to bug.