V jednom smyslu je to "bezpečné" a v jiném nebezpečné. Není bezpečné přidávat ladicí printfs a ze stejného důvodu není bezpečné přidávat kód pro úpravu vyrovnávací paměti stdio v tom smyslu, že je to noční můra údržby. To, co děláte, NENÍ dobrá technika ladění. Pokud váš program dostane segfault, měli byste jednoduše prozkoumat výpis jádra a zjistit, co se stalo. Pokud to nestačí, spusťte program v ladicím programu a projděte jej, abyste mohli postupovat podle akce. Zní to složitě, ale je to opravdu velmi jednoduché a je to důležitá dovednost. Zde je ukázka:
$ gcc -o segfault -g segfault.c # compile with -g to get debugging symbols $ ulimit -c unlimited # allow core dumps to be written $ ./segfault # run the program Segmentation fault (core dumped) $ gdb -q segfault /cores/core.3632 # On linux, the core dump will exist in # whatever directory was current for the # process at the time it crashed. Usually # this is the directory from which you ran # the program. Reading symbols for shared libraries .. done Reading symbols for shared libraries . done Reading symbols for shared libraries .. done #0 0x0000000100000f3c in main () at segfault.c:5 5 return *x; <--- Oh, my, the segfault occured at line 5 (gdb) print x <--- And it's because the program dereferenced $1 = (int *) 0x0 ... a NULL pointer.
Dobře. Mýlíte se. Právě z tohoto důvodu stderr není ve výchozím nastavení uloženo do vyrovnávací paměti.
EDIT:Také jako obecný návrh zkuste místo printf
použít zarážky ladicího programu s. Mnohem usnadňuje život.
Možným způsobem může být bool dodebug
globální příznak a definovat makro, jako je např.
#ifdef NDEBUG
#define debugprintf(Fmt,...) do{} while(0)
#else
#define debugprintf(Fmt,...) do {if (dodebug) { \
printf("%s:%d " Fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__); \
fflush(stdout); }} while(0)
#endif
Pak uvnitř kódu mějte nějaké
debugprintf("here i=%d", i);
Samozřejmě můžete ve výše uvedeném makru udělat fprintf
místo toho... Všimněte si fflush
a připojený nový řádek k formátu.
Zakázání ukládání do vyrovnávací paměti by se pravděpodobně mělo vyhnout z důvodu výkonu.
proč jsou všechny streamy standardně ukládány do vyrovnávací paměti
Jsou ukládány do vyrovnávací paměti z důvodu výkonu. Knihovna se snaží vyhnout systémovému volání, protože to trvá dlouho. A ne všechny jsou ve výchozím nastavení vyrovnávací paměti. Například stderr
je obvykle unbuffered a stdout
je ukládána do vyrovnávací paměti pouze v případě, že odkazuje na tty.
je to tedy bezpečné?
Je bezpečné zakázat ukládání do vyrovnávací paměti, ale musím říci, že to není nejlepší technika ladění.