読者です 読者をやめる 読者になる 読者になる

valgrindとdddの練習

IOI2010の試験環境にはvalgrindとdddとgdbがインストールされているので、valgrindとdddをちょっと使ってみた。

こんなソースを用意。

#include <cstdio>
#include <vector>
using namespace std;

int main(int argc, char **argv) {
    int n = 100;
    vector<int> v(n);
    for(int i = 0; i < 2*n; i++) {
        v[i] = v[i/2] + 10;
    }
    return 0;
}

コンパイル

#!/usr/bin/make -f

CXX = g++
# CXXFLAGS = -O2 -Wall -Wextra -s -static -x c++ -g # IOIのコンパイルオプション
CXXFLAGS = -O2 -Wall -Wextra -g -x c++ # デバッグ用オプション
LDFLAGS = -lm

.PHONY: all

all: test1

IOIのコンパイルオプションでは、ライブラリを静的リンクしてシンボルテーブルとリロケーション情報を削除する。
デバッグ用のオプションでは、デバッグ用の情報を埋めこむ。

$ make test1

普通に実行してみる

$ ./test1
*** glibc detected *** ./test1: double free or corruption (!prev): 0x08b0d008 ***
======= Backtrace: =========
(略)
======= Memory map: ========
(略)
zsh: abort      ./test1

「うわっ…バグっちゃったよ…俺が徹夜して書いたプログラム…もうだめぽ…」

dddを使ってみる

$ ddd ./test1

てけとーに押してブレークポイントを設置
http://gyazo.com/4958b016be1b7cfe591e12bed9e475d0.png
Run!
http://gyazo.com/f92b71a87662f186b462ab0666dcd3f8.png
Contを押すと次のブレークポイントまで行けるなど
で、例えば、ソースコード中のnをダブルクリック
http://gyazo.com/4faa2b1232d22549656f7361cde203d7.png
最適化によって消滅したらしい
iをダブルクリックすると何か見える
http://gyazo.com/68f4e3804e0a6a63aee8b39e3212c027.png
ちなみにvをダブルクリックするとこんなメッセージが
http://gyazo.com/127525a454eb6d90aeab17a3ccb0f41f.png
C++との相性は悪いんかね

さて…残念なことに、エラーが起きているのはv[i]の行ではないことが、必死のマウス連打によってわかってしまった…

valgrindを使ってみる

とりあえずてけとーに

$ valgrind ./test1
==24191== Memcheck, a memory error detector
==24191== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==24191== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==24191== Command: ./test1
==24191== 
==24191== Invalid write of size 4
==24191==    at 0x80485CA: main (test1.cpp:9)
==24191==  Address 0x42d71b8 is 0 bytes after a block of size 400 alloc'd
==24191==    at 0x402569A: operator new(unsigned int) (vg_replace_malloc.c:255)
==24191==    by 0x80485A4: main (new_allocator.h:89)
==24191== 
==24191== 
==24191== HEAP SUMMARY:
==24191==     in use at exit: 0 bytes in 0 blocks
==24191==   total heap usage: 1 allocs, 1 frees, 400 bytes allocated
==24191== 
==24191== All heap blocks were freed -- no leaks are possible
==24191== 
==24191== For counts of detected and suppressed errors, rerun with: -v
==24191== ERROR SUMMARY: 100 errors from 1 contexts (suppressed: 17 from 6)

test1.cppの9行目に問題があると一瞬でわかった!すごい!

ちなみに、さらに有用な情報を見るために必要なオプションのヒントがメッセージの最後のほうに書かれることもあるらしい。

これ便利だな…

続かないかも