GNU/Linux >> Znalost Linux >  >> Linux

Je bezpečné zakázat ukládání do vyrovnávací paměti pomocí stdout a stderr?

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í.


Linux
  1. Jak může proces zachytit stdout a stderr jiného procesu v Linuxu?

  2. Propojení stdout a stderr uvnitř pravidla Makefile

  3. Obnovení stdout a stderr na výchozí hodnotu

  1. Je možné, že linuxový deskriptor souboru 0 1 2 není pro stdin, stdout a stderr?

  2. bash:přesměrování stderr do souboru a stdout + stderr na obrazovku

  3. Zachycení STDERR a STDOUT do souboru pomocí tee

  1. Odesílání úloh SLURM se STDOUT &STDERR zapsanými do souborů s JOB_ID

  2. Nakonfigurovat Shell pro tisk Stderr a Stdout v různých barvách?

  3. Trim s Lvm a Dm-crypt?