競技プログラミングで求められる能力は,通常のプログラミングの場合と多くの共通点を持つ. その一方で,まったく考え方が異なる部分もある.
状況に応じたプログラミングのスタイルを選ぶことが大切.
Problemset
をクリックせよ.gcc -std=c99 hoge.c
とオプションをつけてコンパイルする.
a == b
)せず代入(a = b
)を使用gets
関数など)gcc -Wall -Wextra fuga.c
gdb
コマンドなど.gdb
コマンドでクラッシュ箇所を突き止める.
gcc -Wall -Wextra find_median_broken.c -o find_median_broken
./find_median_broken < find_median_input_1000.txt
zsh: segmentation fault (core dumped) ./find_median_broken < find_median_input_1000.txt
-g
を付加してコンパイルする.gcc -g -Wall -Wextra find_median_broken.c -o find_median_broken
gdb ./find_median_broken
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04.1) 9.2
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./find_median_broken...
(gdb) run < find_median_input_1000.txt
Starting program: /home/hirota/2022_exp2/find_median_broken < find_median_input_1000.txt
Program received signal SIGSEGV, Segmentation fault.
0x0000555555555298 in bubble_sort (n=1000, a=0x55555555b2b0) at find_median_broken.c:14
14 a[j * n] = tmp; /* Should be a[j + 1] = tmp; */
(gdb)
gdb
によるデバッグの手順はプログラミング基礎IIで学んだはずであるので詳細には触れない.gcc -g -Wall -Wextra find_median_broken.c -o find_median_broken
./find_median_broken < find_median_input_10.txt
1.123400
-fsanitize=address
を付加して Address Sanitizer 機能を有効化すればば,プログラムの実行時に配列の範囲外アクセスを検出してエラーであることを教えてくれる.gcc -g -fsanitize=address -Wall -Wextra find_median_broken.c -o find_median_broken
./find_median_broken < find_median_input_10.txt
=================================================================
==1542==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6070000001a0 at pc 0x55fe0844745c bp 0x7fffbf7f7870 sp 0x7fffbf7f7860
WRITE of size 8 at 0x6070000001a0 thread T0
#0 0x55fe0844745b in bubble_sort /home/hirota/2022_exp2/find_median_broken.c:14
#1 0x55fe0844760d in main /home/hirota/2022_exp2/find_median_broken.c:31
#2 0x7f2757c05082 in __libc_start_main ../csu/libc-start.c:308
#3 0x55fe0844720d in _start (/home/hirota/2022_exp2/find_median_broken+0x120d)
Address 0x6070000001a0 is a wild pointer.
SUMMARY: AddressSanitizer: heap-buffer-overflow /home/hirota/2022_exp2/find_median_broken.c:14 in bubble_sort
Shadow bytes around the buggy address:
0x0c0e7fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c0e7fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c0e7fff8000: fa fa fa fa fd fd fd fd fd fd fd fd fd fa fa fa
0x0c0e7fff8010: fa fa 00 00 00 00 00 00 00 00 05 fa fa fa fa fa
0x0c0e7fff8020: 00 00 00 00 00 00 00 00 00 00 fa fa fa fa fa fa
=>0x0c0e7fff8030: fa fa fa fa[fa]fa fa fa fa fa fa fa fa fa fa fa
0x0c0e7fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c0e7fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c0e7fff8060: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c0e7fff8070: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c0e7fff8080: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==1542==ABORTING
std::vector
を使用して要素参照には at()
関数を用いれば添え字範囲を超えたときに out_of_range
例外が送出される.fgets
と scanf
で改行文字を読み込み方が異なることに気付いていない.Problemset
をクリックせよ.