Dwie interesujące prezentacje na temat białek.
Wyjaśnienie czym są białka i jak są zbudowane. Paul Andersen "Proteins":
O człowieku, który buduje własne białka (z wykorzystaniem Lisp-a i LLVM) i chce budować jeszcze, oraz dlaczego C++ się do tego nie nadaje. Christian Schafmeister "Clasp: Common Lisp using LLVM and C++ for Molecular Metaprogramming":
ekstaza, geniusz, przebłysk, olśnienie, półprawdy, półśrodki, przemilczenia, zaćmienia, głupstwa, kłamstewka, oszustwa, hultajstwo, wyrachowanie, nieprawda, nieobiektywność, niepodważalna prawda, nierówność, nieomylność, słuszność, perfekcja, krnąbrność ... niegodziwość
26 lipca 2016
23 lipca 2016
gdb + python
Bardzo łagodne wprowadzenie do tematyki użycia pythona w gdb i jeszcze raz na podstawie CppCon 2015: Greg Law "Give me 15 minutes & I'll change your view of GDB"
Na początku jednak kilka komend, które okazały się całkiem pomoce w procesie nauki:
Na początku jednak kilka komend, które okazały się całkiem pomoce w procesie nauki:
- start - ustawia się na pierwszej instrukcji naszego programu, w zależności od systemu punkt wejścia może mieć różną nazwę, gdb w takim przypadku zachowa się uniwersalnie.
- save breakpoints mybbb - zapisanie breakpointów do pliku. Przydatne, gdy trzeba zamknąć gdb, ale nie chcemy niszczyć dorobku naszej sesji.
- source mybbb - załadowanie breakpointów z pliku
(gdb) python >import os >print('pid %d' % os.getpid()) >end pid 17865Odczyt informacji o breakpointach:
Reading symbols from a.out...done. (gdb) b 8 Breakpoint 1 at 0x400589: file main.cpp, line 8. (gdb) info break Num Type Disp Enb Address What 1 breakpoint keep y 0x0000000000400589 in main() at main.cpp:8 (gdb) r Starting program: /home/user/cpp_gdb_test/a.out is i now 7 Breakpoint 1, main () at main.cpp:8 8 i++; (gdb) python >print(gdb.breakpoints()[0].location) >end /home/user/cpp_gdb_test/main.cpp:8Ustawienie braekpointa z poziomu pythona:
(gdb) python gdb.Breakpoint('11') Breakpoint 2 at 0x4005a1: file main.cpp, line 11. (gdb) c Continuing. is i now 8 Breakpoint 2, main () at main.cpp:11 11 printf("Hello world!!!\n");
22 lipca 2016
[CppCon 2015] recording w gdb
Fajny lightning talk na zeszłorocznej konferencji CppCon 2015 traktujący o przydatnych trikach w procesie debugowania programu:
Postanowiłem przećwiczyć sobie kilka mechanizmów. Najciekawszą rzeczą dla mnie był record, który umożliwia odtworzenie wartości pamięci przy reverse debug-u. Szczególnie przydatny, gdy program pisze po stosie i nie można odtworzyć pechowej sekwencji instrukcji z core dumpa. Linki:
Inne udogodnienia, z których skorzystałem to warunkowy breakpoint w linii 3 (b 26 if v == 4), który zachodzi, gdy zmienna v będzie miała ustawioną wartość na 4. Oraz command, który zostaje wykonany w momencie zatrzymania programu (linie 12-17). Pierwszym argumentem command jest numer porządkowy breakpoint-a, który można uzyskać z info break.
Postanowiłem przećwiczyć sobie kilka mechanizmów. Najciekawszą rzeczą dla mnie był record, który umożliwia odtworzenie wartości pamięci przy reverse debug-u. Szczególnie przydatny, gdy program pisze po stosie i nie można odtworzyć pechowej sekwencji instrukcji z core dumpa. Linki:
- Give Me 15 Minutes and I'll Change Your View of GDB - Greg Law - CppCon 2015.pdf
- https://sourceware.org/gdb/wiki/ProcessRecord/Tutorial
- https://sourceware.org/gdb/onlinedocs/gdb/Process-Record-and-Replay.html
#include <stdio.h> #include <stdlib.h> #include <time.h> void overflow(int v) { char t[10]; if (v == 4) { for (int n = 0; n < 10000; n++) t[n] = 'A'; } } int main() { srand(time(0)); int i; do { i = rand() % 10; printf("i is now %d\n", i); int v = rand() % 100; overflow(v); } while(i != 5); return 0; }Kompilacja, konfiguracja i uruchomienie, trzeba pamiętać o ustawieniu rozmiaru ulimit dla core dump-ów, domyślnie jest to bowiem wartość 0.
ulimit -a ulimit -c unlimited ulimit -a gcc -g main.cpp while ./a.out ; do echo "OK"; done gdb a.out -c coreWynik:
i is now 3 i is now 2 Segmentation fault (core dumped)Stos został uszkodzony, w tym przypadku widać ślad po ostatniej instrukcji i z jaką wartością została wykonana, ale w przypadku bardziej skomplikowanych struktur danych, może być to kłopotliwe.
Core was generated by `AAAAAAAA'. Program terminated with signal SIGSEGV, Segmentation fault. #0 __GI_getenv (name=0x7f15a332b3c2 "BC_FATAL_STDERR_", name@entry=0x7f15a332b3c0 "LIBC_FATAL_STDERR_") at getenv.c:84 84 getenv.c: No such file or directory. (gdb) p i No symbol "i" in current context. (gdb) p v No symbol "v" in current context. (gdb) p t No symbol "t" in current context. (gdb) bt #0 __GI_getenv (name=0x7f15a332b3c2 "BC_FATAL_STDERR_", name@entry=0x7f15a332b3c0 "LIBC_FATAL_STDERR_") at getenv.c:84 #1 0x00007f15a31d7ef2 in __GI___libc_secure_getenv (name=name@entry=0x7f15a332b3c0 "LIBC_FATAL_STDERR_") at secure-getenv.c:29 #2 0x00007f15a321549a in __libc_message (do_abort=do_abort@entry=1, fmt=fmt@entry=0x7f15a332cc7f "*** %s ***: %s terminated\n") at ../sysdeps/posix/libc_fatal.c:80 #3 0x00007f15a32b689c in __GI___fortify_fail (msg=<optimized out>, msg@entry=0x7f15a332cc61 "stack smashing detected") at fortify_fail.c:37 #4 0x00007f15a32b6840 in __stack_chk_fail () at stack_chk_fail.c:28 #5 0x00000000004006bb in overflow (v=4) at main.cpp:14 #6 0x4141414141414141 in ?? () #7 0x4141414141414141 in ?? ()Próba odtworzenia problemu z wykorzystaniem record. gdb przechowa zawartość pamięci, z kolejnych kroków wykonania programu, dzięki czemu można się cofnąć, o jedną komendę (reverse-next), na sam początek nagrywania (reverse-continue), lub skorzystać z innych bliźniaczych komend (reverse-*).
Inne udogodnienia, z których skorzystałem to warunkowy breakpoint w linii 3 (b 26 if v == 4), który zachodzi, gdy zmienna v będzie miała ustawioną wartość na 4. Oraz command, który zostaje wykonany w momencie zatrzymania programu (linie 12-17). Pierwszym argumentem command jest numer porządkowy breakpoint-a, który można uzyskać z info break.
gdb a.out (gdb) b 26 if v == 4 Breakpoint 1 at 0x400748: file main.cpp, line 26. (gdb) b 11 Breakpoint 2 at 0x400686: file main.cpp, line 11. (gdb) info break Num Type Disp Enb Address What 1 breakpoint keep y 0x0000000000400748 in main() at main.cpp:26 stop only if v == 4 2 breakpoint keep y 0x0000000000400686 in overflow(int) at main.cpp:11 (gdb) command 1 Type commands for breakpoint(s) 1, one per line. End with a line saying just "end". >record >continue >end (gdb) r Starting program: /home/user/cpp_gdb_test/a.out i is now 9 i is now 7 i is now 2 i is now 3 i is now 3 i is now 9 i is now 9 Breakpoint 1, main () at main.cpp:26 26 overflow(v); Breakpoint 2, overflow (v=4) at main.cpp:11 11 for (int n = 0; n < 10000; n++) (gdb) (gdb) bt #0 overflow (v=4) at main.cpp:11 #1 0x0000000000400752 in main () at main.cpp:26 (gdb) reverse-next 9 if (v == 4) (gdb) 6 { (gdb) No more reverse-execution history. main () at main.cpp:26 26 overflow(v); (gdb) p i $5 = 9
11 lipca 2016
Gif-y w wysokiej jakości
Znakomity wpis na temat uzysykiwania gif-ów wysokiej jakości:
Moja stara wersja korzystała ze zbyt wielu kroków. W dodatku nie mogłem zmusić programu convert do ustawienia mniejszego opóźnienia pomiędzy ramkami niż 10. W przykładzie poniżej zrezygnowałem ze skalowania.
Moja stara wersja korzystała ze zbyt wielu kroków. W dodatku nie mogłem zmusić programu convert do ustawienia mniejszego opóźnienia pomiędzy ramkami niż 10. W przykładzie poniżej zrezygnowałem ze skalowania.
ffmpeg -i video.avi -r 10 -f image2pipe -vcodec ppm - | convert -delay 10 -loop 0 - gif:- | convert -layers Optimize - output.gifLepsza wersja (także bez skalowania). Kroków jest na tyle dużo, że zamknąłem wszystko w jednym skrypcie, ale convert nie jest już wykorzystywany, ponieważ sam ffmpeg dobrze sobie radzi z tworzeniem plików tego formatu:
#!/bin/sh palette="palette.png" video="video.avi" # filters="fps=15,scale=320:-1:flags=lanczos" filters="fps=25" mogrify -crop 384x362+8+30 +repage $(ls -v *.png) ffmpeg -r 100 -f image2 -i img-%3d.png $video ffmpeg -v warning -i $video -vf "$filters,palettegen" -y $palette ffmpeg -v warning -i $video -i $palette -lavfi "$filters [x]; [x][1:v] paletteuse" -y output.gifObraz jest znacznie płynniejszy.
2 lipca 2016
goto criticism
Przez lata przyjmowałem za pewnik słowa, że "nie należy korzystać z goto" i tak właściwie, to nie pamiętam, żebym to kiedyś zrobił, ba nawet nie miałem okazji widzieć takiego kodu zbyt często. Takie też jest moje wewnętrzne przekonanie. Program korzystający z takiego wyrażenia, nie byłby przyjemny w utrzymaniu. Właściwie więc, po co te mechanizmy w językach nadal istnieją? Wyjątkiem kodu, który miałem okazję analizować były funkcje kryptograficzne, których działanie było zawiłe samo w sobie. Postanowiłem jednak sięgnąć do źródeł całego trendu. I tutaj, nie jest już tak czarno-biało. Ze spostrzeżeń Edsgera Dijkstry ("za") i Donalda Knutha ("przeciw") stworzono dogmat, a sami autorzy zgadzają się, że dla pewnych problemów optymalizacyjnych skorzystanie z goto jest konieczne, chociaż w większości przypadków będzie to symptom źle zaprojektowanego kodu. Odbiegając od specyficznych przypadków dotyczących małej części całej aplikacji, sam Knuth miał jednak nadzieję, że powstaną w przyszłości mechanizmy umożliwiające tłumaczenie wysokopoziomowego kodu, na niskopoziomowy, bez wymogu korzystania z tego wyrażenia. Po 40 latach kompilatory już całkiem nieźle sobie radzą, ale to jeszcze kiedyś sprawdzę.
Subskrybuj:
Posty (Atom)