Help us understand the problem. What is going on with this article?

RustからValgrindのClient Requestを使う

More than 1 year has passed since last update.

Rustを使っているとそれほどメモリリークを気にすることはないですが、それでも必要になるときがちょこちょこあります。Cと連携したりとかunsafeなコードをガンガン使ったりとか。

そんなときはもちろん(?)valgrindを使っていくわけですが、プログラム内でvalgrindにアクセスしたいなんてときもあるわけです。(ほんとか?)

そこでvalgrindはClient Requestという仕組みでvalgrind内部でもってる統計情報とかにvalgrind上で実行しているプログラムからアクセスするためのAPIを提供しています。

このAPIはCから使う前提でAPIが書かれており、マクロを使いマクロ!wというコードなので一見それ以外の言語から触ることができないように見えるのですが、コアはvalgrindに対する特殊なhypercall呼び出しを実行してるだけなのでインラインアセンブラを書けばどの言語からも呼び出すことができます。

Rustには2つの実装があります。

実装してるAPIが多いのはvgrs、対応しているアーキテクチャが多いのはlibvalgrind_requestといったかんじです。

ちょっとvgrsのほうを試してみましょう。ちなみにvgrsは本家のレポジトリが更新されておらずfork先のブランチでなければコンパイルできないのでそちらを使います。

Cargo.tomlをこのようにして、

[package]
name = "vgrs"
version = "0.1.0"
authors = ["Hiroki Noda <kubo39[at]gmail.com>"]

[dependencies]
vgrs = { git = "https://github.com/lummax/vgrs.git", rev = "5252a84bcdc266132181df908f06" }

例にあるコードを少し修正して実行させてみます。

#![feature(core_intrinsics)]

extern crate vgrs;

use vgrs::valgrind;

fn main() {
    unsafe {
        assert!(valgrind::count_errors() == 0);
        let x: u8 = std::intrinsics::uninit();
        println!("{:?}", x);
        assert!(valgrind::count_errors() > 0);
    }
}

まずvalgrindを使わないで実行させてみます。

$ ./target/debug/vgrs
0
thread 'main' panicked at 'assertion failed: valgrind::count_errors() > 0', src/main.rs:12
note: Run with `RUST_BACKTRACE=1` for a backtrace.

2回目のassert!で失敗してpanicしました。

次にvalgrind上でプログラムを実行させてみます。

$ valgrind --leak-check=full ./target/debug/vgrs
$ valgrind --leak-check=full ./target/debug/vgrs            [kubo39:vgrs][git:master]
==5400== Memcheck, a memory error detector
==5400== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==5400== Using Valgrind-3.12.0.SVN and LibVEX; rerun with -h for copyright info
==5400== Command: ./target/debug/vgrs
==5400== 
==5400== Conditional jump or move depends on uninitialised value(s)
==5400==    at 0x13ED82: fmt (num.rs:234)
...
==5400==  Address 0x6220000 is in a rw- anonymous segment
==5400== 
0
==5400== 
==5400== HEAP SUMMARY:
==5400==     in use at exit: 0 bytes in 0 blocks
==5400==   total heap usage: 7 allocs, 7 frees, 2,032 bytes allocated
==5400== 
==5400== All heap blocks were freed -- no leaks are possible
==5400== 
==5400== For counts of detected and suppressed errors, rerun with: -v
==5400== Use --track-origins=yes to see where uninitialised values come from
==5400== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 0 from 0)

メモリの未初期化まわりでエラーが4つでたので、2つめのassertの条件を通るようになりpanicしなくなりました。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away