Quantcast
Channel: Futurismo » C++
Viewing all 42 articles
Browse latest View live

ごちゃまぜスパゲッティのメサイア到来?!レガシーコードをC言語のTDD用フレームワーク『Fake Function Framework (fff)』ですっぽんぽんにする

$
0
0

タイトルか下品なのは、仕事でコーディングさせてくれなくてレガシーコードの保守ばかりさせられるストレスからです。以前、こんな記事を書きました。

CMockは素晴らしいツールで、正直これがないとこの3ヶ月で心がへし折られていたと思う。しかし今日は、CMockに対向できるような素晴らしいツールを発見したので紹介。その名も、

FFF

ファイナルファンタジーではないが、魔法のようなツールだ。

FFFってなに

Fake Function Framework。ダミー関数を自動生成してくれる、『C言語』のためのツール。フェイク関数のフレームワークといいつつも、実際はスタブ関数やスパイ関数などなど、いろいろ生成するツールだ。

githubからダウンロードできる。

基本編

一番くわしいリファレンスは、githubのReadme.mdを以下はそれを参考に、いろいろと実験。

git clone git@github.com:meekrosoft/fff.git

xUnitフレームワークは、Unityを利用します。

はじめの一歩

定形の宣言。fff.hのなかに、すべてが集約されている。テストコードに以下を追記。

// Test_uhauha.c
#include "fff.h"
#include <string.h>
DEFINE_FFF_GLOBALS;

fff.hのなかで、memsetを利用しているようなので、string.hかが必要。

FFFでDummyする

まずは、ダミー関数を。hogehogeの実体をコンパイルすることなく、uhauha関数からhogehogeを呼び出す。

// uhauha.c
#include "uhauha.h"
#include "hogehoge.h"

void uhauha(void)
{
  hogehoge();
}

// hogehoge.h
int hogehoge(void)

void hogehoge(void)型を置き換えるには、テストコードに以下を追加する。

// Testuhauha.c
FAKE_VOID_FUNC(hogehoge);

これで、ダミー関数が宣言されて、コンパイルが通る。

これだけなのです!!魔法みたい!ウッハウハですね。

FFFでスタプする

hogehoge()をスタブ関数にします。必ず1を返すようにする。。

// uhauha.c
int uhauha2(void)
{
  return hogehoge2();
}

// hogehoge.h
int hogehoge2(void)

テストコードに以下を宣言。

// Testuhauha.c
FAKE_VALUE_FUNC(int, hogehoge2);

そして、実際のテストでは、1を返すようにhogehoge2fake.returnvalに値を入れる。

void test_uhauha2(void)
{
  hogehoge2_fake.return_val = 1;
  TEST_ASSERT_EQUAL(1, uhauha2() );
}

これで、hogehoge2は必ず1を返すフェイク関数ができる。

これだけなのです!!魔法みたい!ウッハウハですね。

FFFでスパイする

Spy関数も生成できるようです。

hogehoge3()に渡された値をスパイして、あとで結果をAssertします。

// uhauha.c
void uhauha3(int x)
{
  x++;
  hogehoge3(x);
}

// hogehoge.h
void hogehoge3(int);

テストコードはこちら。hogehoge3fake.callcountで呼ばれた回数を、hogehoge3fake.arg0valで呼ばれた値を検証している。

// Testuhaha.c
FAKE_VOID_FUNC(hogehoge3,int);

void test_uhauha3(void)
{
  uhauha3(1);

  // check how many times hogehoge3 called.
  TEST_ASSERT_EQUAL(hogehoge3_fake.call_count, 1);
  // chech what value was given
  TEST_ASSERT_EQUAL(hogehoge3_fake.arg0_val, 2);
}

これで、hogehoge3をスパイできる。

これだけなのです!!魔法みたい!ウッハウハですね。

応用編

 スタブとスパイの合わせ技

スタブしつつ、スパイの検証もできる。以下のように宣言。たとえば、

int hogehoge4(int);

をスパイしつつフェイクするには、以下を書く。

FAKE_VALUE_FUNC(int, hogehoge4,int);

シーケンス制御の検証

ほかにも、シーケンスの検証も可能。シーケンスのチェックこそがモッキングフレームワークなのだよ!詳細は省略。

カスタム関数を利用してフェイク、スパイする

登録した関数がコールされた時に、自分で作成した関数に飛ばすことができる。

 hogehoge5_fake.custom_fake = hogehoge_custom_fake;

のように宣言して

void hogehoge_custom_fake(){}

みたいに、自分が関数を用意する。プリプロセッサ接合部で置換するので、関数ポインタやリンク時の整合部を意識することなく、さくっと自前関数に飛ばせる。便利(・∀・)。

個人的最大の課題 データを渡す関数のモック

自分の扱っているコードは、メモリ獲得した構造体データを引数にして関数に渡すことがほとんど。こんな感じ。

//hogehoge.h
typedef struct hogehoge {
  int time;
  int status;
  int factor;
}HOGEHOGE;
void hogehoge5(HOGEHOGE *hogehoge);

//uhauha.c
void uhauha5(void)
{
  HOGEHOGE *hogehoge = (HOGEHOGE *)calloc(1,sizeof(HOGEHOGE));
  hogehoge->time   = 1;
  hogehoge->status = 2;
  hogehoge->factor = 3;

  hogehoge5(hogehoge);
}

こういうhogehoge5をチェックするには、自前のスパイ関数を作成して検証していた。fff.hを利用すれば検証がサクットできる。

HOGEHOGE last_hogehoge;
void hogehoge5_spy(HOGEHOGE *hogehoge)
{
  memcpy(&last_hogehoge,hogehoge,sizeof(HOGEHOGE));
  free(hogehoge);
}

void test_uhauha5(void)
{
  hogehoge5_fake.custom_fake = hogehoge5_spy;
  uhauha5();

  TEST_ASSERT_EQUAL( 1, last_hogehoge.time);
  TEST_ASSERT_EQUAL( 2, last_hogehoge.status);
  TEST_ASSERT_EQUAL( 3, last_hogehoge.factor);
}

感想

以前の記事で、『プリプロセッサ接合部』について書きました。

このfffは、『プリプロセッサスゲーΣ(゚Д゚ノ)』と思わせるツールでした。C言語のプリプロセッサの底力を垣間見たフレームワーク。レガシーC言語バンザイヽ(´ー`)ノ

CMockは便利だが、xUnitがUnityに限定されてしまう。それに対してこのfff.hは、移植性がとても高そうだ。評価してないけど、いろんなフレームワークでいっしょに利用できそう。C言語のフレームワークだが、extern "C"のテクニックをりようすることで、C++系のxUnitフレームワークでも利用可能。

CMockはRubyスクリプトでダミー関数を一気に生成することができる。

fffは必要なダミー関数を必要なだけ作成する点が異なる。自分の扱っているコードはテストがあるなんという金持ち環境ではなく、技術的負債で潰れかけているので、ねじ込むようにテストを書くにはCMockが必須う。

CMockだと、引数に構造体ポインタを渡す関数をうまくモックできなかった(やりかたがわからないだけかも)。そういう場合は、結局自分でモック関数を作成していた。しかし、fffを利用すればちょっと楽がデキそうた。

Reference


gccよりも高速な次世代コンパイラClangをCygwinでつかってみた

$
0
0

最近流行のコンパイラ、Clangを試してみました。

Clangとは

Clangとは、gcc,iccのような、コンパイラの一種です。プログラミング言語C、C++、Objective-C、Objective-C++用。

Clangの最終目標は、GNU gccの置き換えらしい。

静的解析能力やリファクタリング機能などももつため、IDEとの結合も目標らしい。

以下は、setreduceという、Googleのエンジニアが開発しているリファクタリングツールのデモ動画。

Clangを利用すると、コンパイラ時間がgccに比べて短くなるらしい。今回の目的は、それを確かめるためです。Clangのパフォーマンスがgccよりも良かったら乗り換えてみる。

Cygwinへのインストール

setup.exeに用意されているようです。自分はapt-cygで取得。

$ apt-cyg install clang
$ apt-get install llvm
$ clang -v
clang version 3.1 (branches/release_31)
Target: i386-pc-cygwin
Thread model: posix

取得できたものは、3.1。現在の最新は、3.3なので、少し古い。

ベンチマーク

C言語でかかれたプロジェクトをベンチマークとしてコンパイルしてみます。Clangのコンパイラオプションはgccと互換性があるので、makefileのCCオプションを変えるだけで行ける。

tree project

curl -LO http://mama.indstate.edu/users/ice/tree/src/tree-1.6.0.tgz
  • gcc 7.8s
  • clang 9.5s

なんと、gccの勝利。あれ(・・?

screen project

git clone git://git.sv.gnu.org/screen.git
  • gcc 1:34
  • clang 1:02

おお、30秒も速かった!Clangの圧倒的勝利。

Warningメッセージもカラー付きでわかりやすく表示してくれる。

process.c:6272:35: warning: operator '?:' has lower precedence than '+'; '+' will be evaluated first [-Wparentheses]
strncpy(p, buf, 1 + (l < len) ? l : len);
                ~~~~~~~~~~~~~ ^

eclipseからClangでコンパイルする(4.3ではバグってた)

LLVM Tool Chain for Eclipse CDTプラグインをインストールする。

プロジェクトを右クリックして C/C++ビルド > ツールチェーン・エディタ を選択。

互換ツールチェーンのみ表示のチェックを外すと、ツールチェーンにLLVM Clang(cygwin)が選択できるので、選択。

ただし、Eclipse最新版4.3で試したところ、2度めに設定画面を開くとNullPointerExceptionが発生する。つまり、まだバグっているから使わないほうがいいということ。

最後に、ウィンドウ -> 設定 -> LLVM を選択。Library path libstdc++ がある場所のパスを通す。自分の環境では、C:\cygwin\lib\gcc\i686-pc-cygwin\4.5.3

これで、EclipseからClangでコンパイルできた。

TopCoder SRM : 587 Div2 Level1 Level2

$
0
0

TopCoder参戦!今日は、定時退社をしようとおもったけれども結局できずに、会社近くのカフェからTopCoder参戦した。

今週から、CourseraのAlgorithms PartⅠを受講中。本格的に、アルゴリズムの勉強に力を淹れている。


Algorithms, Part I | Coursera



Level1は、過去問で似たような問題を解いたことがあるので、mapを利用して難なくクリア。

Level2は、問題の意味を理解するのに苦戦。最後は、やっつけで条件を追加したらテストをパスしたのでそのまま提出。案の定、システムテストで落とされた。

TopCoder SRM 590 div2 250

$
0
0

TopCoderに参戦!

深夜のTopCoderは起きてるのだけで辛い。。。>_<

CourseraのAlgorithms Part1のノルマをこなすために、この日は朝からずっとアルゴリズム漬けだった。15時間の勉強のあとに、TopCoder参戦。

Courseraはイバラの道だったな。。。休日が課題で潰れる。もっと平日定時退社できればいいのだけれども。

そんなこんなで、疲れ果ててほとんど問題が解けなかった。いつになっても全く成長できない。。。


 

『C言語とC++』メリットとデメリットについて調べてみたメモ

$
0
0

Courseraで 『C++ for C Programer』という講義を受講しています。そこで、今日は、C++がC言語よりも優れている点、またはその逆を調べてみました。

講義では、マーガリンはバターから作られるから、バターよりベターというオヤジギャグでC++のCに対する優位性が説明されるが、ほかにも以下の様な理由があげられる。

  • More Type Safe
  • More Libraries
  • Less reliance on preprocessor
  • OO vs imperative

そこで、ネット上の意見も調べてまとめてみた。

※自分の意見ではなくて、あくまでネット上の情報をまとめたもの。

C++がCよりも優れている点

  • C++はC言語を内包している、互換性がある。
  • オブジェクト指向を言語がサポートしている。
  • 豊富なライブラリ群

CがC++よりも優れている点

  • 実行速度、パフォーマンスが高い。
  • メモリ使用量の小ささ。
  • C++よりも文法がシンプル。

まとめ

ハードのレジスタをいじるような組込み系はCが優位、アプリケーションならばC++が優位と読めた。

C言語でもオブジェクト指向ライクな実装はできるけれども、それをしないのは、(すくなくとも自分の職場では)、過去の資産が手続きで書かれているためと、OOに対する知識のなさからだと思う。

あとは、OOライクでないと、テストコードがとても書きにくい。TDDが好きなので、C言語よりもC++に魅力を感じる。いまはC言語を仕事でつかっているけれども、早くC++を身につけてC++の仕事に移動したい。

Links

C言語でのローカル変数宣言は、ブロックの途中でも宣言可能らしい(C99)

$
0
0

C++の勉強をしていると、こんなことをよく言われる。

C++では、ローカル変数はメソッド内のどこでも宣言できる。C言語はブロックの先頭で宣言しなければいけない。そこがCとC++の差だ。

実は、そんなことはなかった!C言語でも、ローカル変数を関数内のどこでも宣言できる。

むかしは、ローカル変数は関数の頭で宣言しないといけなかった。しかし、C99で仕様拡張があった。

C99以降のC言語ではローカル変数を関数内のどこでも宣言できるようになったらしい。スコープは、その宣言された直後から開始される。ただし、VisualC++2008/2010/2012 のいずれも、この機能には対応してい無いらしい(これは未検証」

たとえば、こんなのもエラーしない・・・?

#include <stdio.h>
int main(void)
{
  printf("hogehoge\n");
  for(int i=0; i<10; i++)   printf("%d",i);
}

エラーした。

$ gcc local_val.c
local_val.c: 関数 ‘main’ 内:
local_val.c:4:3: エラー: ‘for’ ループ初期化宣言は C99 モード内でのみ許可されています
   for(int i=0; i<10; i++)   prinntf("%d",i);

コンパイラは、 gcc 4.8を利用。

$ gcc --version
gcc (GCC) 4.8.1

こんどは、C99をサポートするコンパイルオプションをつけると通った。

$ gcc -std=c99 local_val.c

リーダブルコードでも、スコープを狭めたほうが可読性が上がるし、こっちの仕様のほうがいいな。

C++での動的配列(set,map)の使い方まとめ

$
0
0

C++での動的配列(set,map)の使い方についてまとめます。

setの使い方

setとは、自動でソートされる動的配列を扱うためのSTLです。

数学でいうところの"集合"に対応するものですが、setは要素数が有限です。

宣言

#include <set>
using namespace std;

set <string> s;

関数

要素数を調べる
s.size();
要素を追加する
s.insert("hoge");

同じ要素を追加しても、要素数は1つのまま。

s.insert("hoge");
s.insert("hoge");
s.size(); // = 1
要素を検索する
s.find("探すもの")

if( s.find( "hoge" ) == s.end() )
{
    cout << "Not Found" << endl;
}
else
{
    cout << "Find" << endl;
}
要素をすべてクリアする
s.clear();

よくある使い方

文字列Sのなかの文字の要素数を調べる。

int getNumber(string S) {

  set <string> s;
  for(int i=0; i<S.size(); i++) {
    s.insert(S[i]);
  }
  return s.size();
}

pairの使い方

pairは2つの値をペアで扱うためのSTLです。

宣言
#include <utility>
using namespace std;

pair <string, int> p;
参照
p.first();  // 一つ目の要素
p.second(); // 2つ目の要素
要素を追加する
p.first  = "hoge"
p.second = 3

pair<int, string>( "hoge", 3 );
p = make_pair("hoge",3);

mapの使い方

map とは、連想配列を扱うための STLです。

(キー, 値)のペアでデータが保持されます。「任意の型のキー」から「値」を引く辞書を作成できます。

setは(キー)のみを要素にしていますが、mapはpairを要素とします。

宣言
#include <map>
using namespace std;

map <string, int> m;
参照
m.first();  // キーへのアクセス
m.second(); // 値へのアクセス
要素を追加する
s["hoge"] = 3;
s.insert(pair<string, int>("hoge", 3));
s.insert(make_pair("hoge", 3));
要素を検索する

setと同じなので、省略。

要素をクリアする
m.clear();

よくある使い方

mapの要素にアクセスするには、イテレータを利用するのが便利です。

map<string, int>::iterater it;

また、要素の先頭アクセスするには、begin(),最後にアクセスするにはend()を利用します。

m.begin(); // 先頭要素にアクセス
m.end();   // 最後の要素にアクセス

文字列Sのなかの文字で一番数が多いものの最大値を求めます。

int getNumber(string S) {
    map <string, int> m;
    for(int i=0; i < S.size(); i++) {
      m[S[i]]++;
    }

    int max = 0;
    map<string, int>::iterator it;
    for(it = m.begin(); it!=m.end(); it++ ) {
      if( max < it->second ) max = it->second;
    }
    return max;
}

TopCoder用テンプレート(C++)

$
0
0

TopCoder用テンプレート

自分のテンプレートを公開。随時追加中。

補助関数

よくつかう補助関数をまとめます。補助関数を利用するには、 以下をインクルード。

#include<algorithm>
using namespace std;

最大・最小

int = 1, int j = 2;

// 最大値
rslt = max(i,j); // rslt = 2

// 最小値
rslt = min(i,j); // rslt = 1

スワップ

ポインタを指定する必要はありません。sortの実装の時などに。

// 交換
swap(i,j) // i=2,j=1

『Modern C++ with TDD』学習メモ(Chapter6-11)

$
0
0

『Modern C++ with TDD』後半分の学習メモです。前半部分は、ココ。

『Modern C++ with TDD』学習メモ(Chapter2-5) | Futurismo

各章の概略

  • Chapter6: Incremental Design 主にリファクタリングの話題。どうやってシンプルなコードを作っていくかを実践する。1行でも関数として抽出する。インクリメンタルに、デザインを作り上げていくその開発スタイルが『モダン』といっている。
  • Chapter7: Quality Tests テストの書き方について。FIRSTの原則の紹介。一つのテストでひとつのことを検証する、テストの名前付に慎重になる。そして、テストコードのリファクタリングの実践、ほかTips。
  • Chapter8: Legacy Challenges 実際のレガシーコードを使ったリファクタリング体験。いきなり200Stepsのうんこメゾッドが出される。ここでは、CppUTestを使う。テクニックは『レガシーコード改善ガイド』に載っているもの。この章は,必読。涙がでるほど素晴らしかった。
  • Chapter9: TDD and Threading マルチスレッドのプログラムに対するTDDのアプローチの紹介。正直、ここは理解できなかった。
  • Chapter10: パフォーマンスや受け入れテスト、TPPなどの、TDDを発展させた話題を取り扱う。
  • Chapter11: Growing and Sustaining TDD おまけのような、未分類の小さな話など。Code Jodo、マネージャーへのTDDの説得方法、参考リンクなどなど。

StudyMemo

Small Methods

一行の論理でもメソッドとして抽出する。その理由は、

  • Methods名が機能を現してコメント代わりになる。
  • 重複を排除するためのスタートになる。
  • パフォーマンスは瑣末なものだ。

Chapter6は 1990年代では、奇妙なことがよいこととされてきた、と結論づけられる。いまは、このような過剰なリファクタリングは奇妙に見えるけれども、20年後はこれ普通になるのだよ、と。

Chapter10では、実際に簡単な数値実験が行われる。inlineメソッド、Smallメソッド、inline無効にした場合で実験。inlineメソッドとSmallメソッドのパフォーマンスはほぼ同じ、だけどinline無効メソッドは時間がかかる。

最近のコンパイラは頭がいいから、小さな関数は勝手に最適化してくれる。なので、Smallメソッドはパフォーマンスを阻害しないと。他人のいうことに耳を傾けてはいけない、彼らは同じことをいうだけなので。

ここにも、数値実験があった。このリンクの記事はリファクタリングについてよく語っていて興味深い。数値をみると、なるほどと思う。

自分でも実験してみた。だいたい、変わんない。

パフォーマンスが懸念だが、そもそもパフォーマンスがネックというのは迷信なのか?オーバーヘッドは無視していいのか?未来は、パフォーマンスは瑣末な問題になるのだろうか?

コードにコメントを書くことについても、『コード自身が語っているのに、なんで冗長なコメントを書くの』と。

FIRSTの原則

良いテストは以下の5つに従う。

  • F First
  • I Isolated
  • R Repeatable
  • S Self-Verifiying
  • T Timely

Mikado Method

ミカドメソッドとは、大規模なコードをリファクタリングするための方法論。 別記事にまとめました。

Code Kata

これは別記事にまとめました。

Transformation Priority Premise

ボブおじさんが考案した、TDDをより簡単に実施するための方法。

“Uncle Bob” Martin – The Transformation Priority Premise from 8th Light on Vimeo.

モダンディでイケイケなTDDの最新動向が集結!『Modern C++ Programming with Test-Driven Development』

$
0
0

『Modern C++ Programming with Test-Driven Development』をだいたい読み終わりましたので、感想を書きます。

各章の概要

各章の概要と、学習メモは以下のエントリを参照。

初めは懇切丁寧にTDDの基礎が述べられているので、モダンだからと言ってもTDD実践入門に最適。 使われているフレームワークは、

  • GoogleMock
  • CppUTest

Mockに関する説明は少なかったように思う。一部のテクニックを書くのではなくて、まんべんなく書かれているイメージ。

また、コンパイラはC++11を使っていて、見慣れないC++の文法がたくさん出てきたのが少しつらかったところ。このへんも、モダン。

写経について

この本は、ところどころ写経しながら読みました。写経環境の導入手順は以下にまとめました。あとから思うと、Ubuntuが一番楽じゃないかと思う。

電子書籍なので、本からウェブ上のソースコードにリンクが張ってあります。すべてをそのまま写したところもありますが、ちょっと手を抜いて、サンプルコードをコピペしながら読んだところもあります。 サンプルコードを実際に動かしたり、diffを取ったりしながら読んだほうが、理解が深まりますね。

感想

モダン!( ー`дー´)

この名に恥じない内容だった。新しいテクニックや考え方にワクワクして、明治時代の人がザンギリ頭に触れる喜びを感じた。

西洋のTDD界ではkataだとかdojoだとかMikadoだとかがブームだというおかしなジャポニズムを初めて知った。そんなニッポンはShakyoがブーム?この本を通してKataを知ったのは収穫だった。今後の勉強の進む方向はコッチだ。

個人的には、『test driven development for embedded c』に続く良書。ただし、かつての感動はなかった。もともと、前半の内容は知っていることが多かったので。C++というのも、Cに比べると疎遠なので。

サブタイトルが『Code Better, Sleep Better』となっている。

Code Betterは、リファクタリングについての話題が多め。実際のサードパーティから依存関係を取り除いたり、実際のレガシーコードを利用したリファクタリングしたりする。理想的なTDDなどありえなくて、現実はとてつもないレガシーコードと戦わなければいけない。現実に則した本だ。我らの味方だ。

Sleep Betterがなにを暗示しているのかワカラなかったので、そろそろ寝ます。おやすみなさい(´-ω-`)

自由自在にコード内を飛び回る!Eclipseのコードリーディング機能が便利

$
0
0

Eclipseには、コードを読みやすくするための様々な機能が備わっています。

GUIだからマウスをたくさんつかうんだろうという迷信がありますが、実際はキーポードから手を離さなぽことがおおいです。

キーバインドを巧みに利用して、コード内を自由自在に飛び回るためのテクニックを紹介します。

宣言を開く(F2,F3)

関数や宣言の場所へジャンプすることができます。いわゆる、タグジャンプ、EmacsのGNU Grobalのようなもの。もっともよく利用する機能です。

F3で飛んで、Alt + 左で元に戻る。これでソースコード内をマウスを利用せずにピョンピョンと移動することができます。

F2を押すと、飛ばずにポップアップで宣言の場所を表示することができます。

呼び出し階層を開く(Ctrl+Alt+h)

関数がメソッドがどこの関数から呼ばれているかを順々に表示してくれる機能。

リファクタリングの時の修正による影響範囲を調査する時、重宝する機能。

型階層を開く(F4)

クラスの型を階層的に表示てくれる機能。継承関係が分かる。

C++だと機能するけれども、Cだとよくわからない機能。あまり利用しない。

エディタバッファを開く(Ctrl + x + b)

ファイル間の移動は、ショートカットで新規にファイルを開くこともあるけれども、もともと開いているファイルに飛ぶこともデキる。

このキーバインドは、Emacsキーバインドを設定しているので、Emacsに慣れている人はそのキーバインドをそのままEclipseでも利用できる。すなわち、Ctrl + x + b。

Alt + 左で前へ戻り、Alt + 右で次へ進むことができる。もはやブラウザでWebページを見るような感じ。

検索で飛ぶ

デフォルトのEclipse CDT検索機能は利用しません。代わりに、プラグインを利用します。

検索結果をクリックするだけで検索箇所へジャンプできるので、コンソールからgrepして検索するよりも効率がよいです。

C++11のrandomライブラリで1から10の乱数を生成する方法のメモ

$
0
0

C++で乱数を利用する方法について調べてみた。

やりたいこと

1~10の間で、ランダムな数字を取得する

実装方法

C++には、長らく乱数生成はC言語に頼ってきた歴史があるようだが、C++11でようやくrandomライブラリが標準実装されたようだ。

利用するためには、以下をインクルード。

#include 

覚えないと行けないことが2つある。

  • 乱数生成エンジン ・・・ 乱数を生成する。
  • 分布生成器 ・・・ 生成された乱数を分布に従わせる。一様分布、正規分布、ベルヌーイ分布、ポアソン分布、など。

乱数生成エンジンは種類がたくさんあり、正直どれをつかえばいいのかわからないので、とりあえずコレ。

  // 予測不能な乱数生成器(class   
  std::random_device
  // メルセンヌツイスターの32ビット版(typedef)
  std::mt19937

分布は一様分布を利用。これは、intとdoubleでつかうエンジンが異なる。

// 整数型 std::uniform_int_distribution // 浮動小数点型 std::uniform_real_distribution

追記

randomライブラリは実行速度がrandに比べて早くないことが判明!なので、srand,randを使った方法も追記。srandはループの外で宣言する必要がある。

実装

-std=gnu++0xをコンパイルオプションにつけることを忘れないように。

こんな感じで、生成されました。

5.28957
8.79693
5.23333
1.76491
3.95931
5.52467
8.1513
6.85362
1.68268
9.75644

Links

C++での優先順位付きキューの使い方まとめ(PriorityQueue)

$
0
0

優先順位付きキューのをPriorityQueueという。

キューの中で最大(最小)のものを抜き出す場合などに利用する。

宣言

デフォルトでは大きい順でpopされるので、最小のものをpopで取り出すには、greaterを宣言時に追記する。

#include <queue>
using namespace std;

priority_queue <int> maxpq; // default 大きい順
priority_queue<int, vector<int>, greater<int> > minpq; //小さい順

関数

要素を追加する(push)
pq.push(1);
先頭の要素を取り出す

最大(または最小)の先頭を取り出します。

pq.pop();
要素を調べる
// キューがからかどうかを調べる
pq.empty()

// 要素数をしらべる
pq.size();

// 次に取り出される要素を調べる
pq.top();

Sample

昇順に取り出す

#include <queue>
#include <iostream>
using namespace std;

int main()
{
  priority_queue<int> pq;

  pq.push( 2 );
  pq.push( 1 );
  pq.push( 3 );

  cout << pq.top() << endl;
  pq.pop();
  cout << pq.top() << endl;
  pq.pop();
  cout << pq.top() << endl;
  pq.pop();

  return 0;
}

実行結果

3
2
1

降順に取り出す

#include <queue>
#include <iostream>
using namespace std;

int main()
{
  priority_queue<int, vector<int>, greater<int> > pq;

  pq.push( 2 );
  pq.push( 1 );
  pq.push( 3 );

  cout << pq.top() << endl;
  pq.pop();
  cout << pq.top() << endl;
  pq.pop();
  cout << pq.top() << endl;
  pq.pop();

  return 0;
}

実行結果

1
2
3

おまけ

ダイクストラ法の実装をする際に、C++のSTLがあるとは知らずに、自前で最小優先キューを実装しました。STLを利用すればよかった。

このJava Sourseを参考にC++に書きなおした。
ftp://ftp.cs.princeton.edu/pub/cs226/bins/MinPQ.java

UnionFindアルゴリズムを実装してみた

$
0
0

UnionFindをC++で実装した。

UnionFindとは、2つの異なる集合がつながっているかを調べるアルゴリズム。詳しくは以下。

Implement

以下のJavaでかかれた実装をC++版に書き直してみた。木構造にデータを保持する場合と、そう強いない場合の2つを実装。

C++でのSTLアルゴリズムの使い方まとめ(sort)

$
0
0

C++ STLの algorithmで便利そうなものをメモしてきます.

並べ替え・ソート(sort)

  • 並べ替えを実施します。
  • vectorなどのランダムアクセス可能なコンテナで利用可能。
  • ロジックはクイックソートを利用している。

使い方

sortの引数として、並べ替えたい初めと終わりのイテレータを渡す。たいていは begin(),end().

sort(a.begin(), a.end());

デフォルトでは小さい順(less())に並べ替えられる。大きい順に並べ替える時は、以下のようにgreater<>()を引数として渡す。

sort(a.begin(), a.end(), greater<int>());

#include <algorithm>
#include<vector>
#include<iostream>

using namespace std;

int main()
{
  vector<int> a;
  a.push_back(3);
  a.push_back(1);
  a.push_back(2);

  sort(a.begin(), a.end());
  for( auto x : a ) cout << x;
  cout << endl;

  sort(a.begin(), a.end(), greater<int>());
  for( auto x : a ) cout << x;
  cout << endl;
}

実行結果

$ g++ -std=c++11 sort.cpp
$ ./a
123
321

[Coursera]C++ For C Programmersを受講しました

$
0
0

Cプログラマなので、C++を勉強するために『C++ For C Programmers』を受講しました。

概要

C++の初級的な話題が紹介される。この講義でC++の基礎がマスターできる内容。Cプログラマを対象にしているため、Cとの比較やC++のここがスゴイのだという説明も出てきて、Cしかしらない自分にはこのCについての伏線が嬉しい。

また、なにかにつけてC++11の話題がガッツリ紹介されるので、C++11 For C++98 Programmersというタイトルのほうが実は適切な気がする。

オープニングにJAZZが流れて、ダンディさあふれるのIra Pohl教授が現れる。

話し方がカメみたいにものすごくゆっくりなので、English的な壁は大丈夫だった。スライドにカラーペンで書き込みながら説明されるので、臨場感がある。(しかし字がけっこうきたない)

参考書

参考書は、ネット上にある無料のものと、有料のものがある。

  • C++ by Dissection
  • C++ For C Programmers


が、自分は利用しなかった。どちらかというと、副読本としては、かつて挫折した独習C++を読んでた。

各回の概要

Week1 C++ as a Better C

A言語からC言語までに至る歴史の説明。そして、C++がC言語に比べてなぜ優れているかを解説する。課題は、C言語でかかれたコードをC++に書きなおす。ここでC++独特の表記をならう。

week2 C++: Basics of Generics and Classes Template

templateが出てくる。より汎用的で、再利用可能な書き方について学ぶ。課題はダイクストラ法の実装。どのへんがC Programmerのためなのだ? モンテカルロ法やPriorityQueueを使いこなす必要があり、難しい。

week3 C++: Class Constructors and Destructors

コンストラクタ、デコンストラクタの説明。または、List構造の説明。Assignmentの実装方法に関するフォローの講義も入る。

week4: C++: Minimum Spanning Tree & Standard Template Library

auto,継承、friend関数などなど。ここで、STLの解説とイテレータという概念が出てくる。だんだんC++ぽくなってくる。Assignmentは最小スパニングツリーをプリム法かクラスカル法で実装。

week5: C++ 11 Standard; Containers, Iterators and Algorithms

主にここではSTLの説明。コンテナ、イテレータ、アルゴリズムの三本柱が詳しく解説される。lambdaの使い方も紹介されるが、理解できなかった。

week6: Hex, the game and C++ Inheritance

後半の大きな話題である、Hex gameの説明が入る。また、重要な概念である、もここで解説。

Module 7: Min-Max and C++11 Classes; Alpha-beta and Polish

Copy Constactor や Move Costractorなど。またHex Gameを実装するための方法が解説される。ミニマックス法やアルファ・ベータ法など。ここで、このCourseのサムネイル画像がチェスの理由を理解した。この先生はチェスがとても好きらしい。チェスにおけるAIの実装方法なども出てくる。

後半の課題である、Hex Gameを 3weekにわたって実装する。この課題で、C++のfeatureを全部注ぎ込みなさいと言われて、けっこう頑張った。

Module 8: Monte Carlo Evaluation; the C++11 Standard

例外処理、スレッド処理などなど、今までで解説していないC++のfeatureももれなく紹介。また、C++中級への道として、簡単なデザインパターンが紹介される。

おわりに

For C Programmerな部分は実はweek1だけだった気がした。グラフ理論やゲーム理論が出てきて、『いったいどのへんがFor C Programmerナンダヨ!』と全生徒が唸ったに違いない。

Cしかできない自分にとっては、まさにうってつけの授業だった。

Hex Game

スレッドとタスクの違いについてしらべてみた(C++/Linux)

$
0
0

今日、タスクとスレッドの違いについて質問された。

うまく説明できなかった。

人間失格。

ということで、ここで反省しようと思う。

タスクとスレッドの定義について

Wikipediaから引用する。

スレッド

スレッド(thread)とは、CPU利用の単位。
プロセスに比べて、プログラムを実行するときのコンテキスト情報が最小で済むので切り替えが早くなる。
スレッドは、thread of execution(実行の脈絡)という言葉を省略したものである。

ある処理を単一のスレッドのみを用いて動作させる環境もしくは手法をシングルスレッドという。
対して、複数のスレッドが同時に動作することをマルチスレッドという。
プログラム(概ねプロセス)の開始時にはメインとなるスレッドが動作する。
必要に応じてその他の処理をするスレッドを作り、実行させる事も出来る。

タスク

1つのタスクは、1つ以上のプロセスから構成され、1つのプロセスは、1つ以上のスレッドから構成される。

プロセスと同義。スレッド (コンピュータ)と同義。タスク並列性などの用語では両者を区別しない場合もある。

OSから見た処理の実行単位。
通常はスレッドが実行単位となるが、OSによってはプロセス(複数のスレッドを含むプログラム全体)を1つの実行単位としてみる場合もある。
一つのアプリケーションソフトが行っている作業全体を一つのタスクと扱う場合が多く、この場合は「プロセス」に近い意味合いになる。

調査結果

わからん。

C++からアプローチ

C++11では、threadライブラリがあるので、使ってみる。

 g++ thread.cpp  -pthread -std=c++11 -Wl,--no-as-needed

実装結果

わからん。

タイマをつかって比べてみる

タイマをつかってみた。

スレッドライブラリをつかったマルチスレッドプログラムは5秒かかる。

スレッドライブラリをつかってないシングルスレッドプログラムは15秒かかる。

実装結果

ちょっとわかった。

まとめ

C++/Linux環境だと、コンパイルした a.outを実行したものがタスク(プロセス?)

% ./a.out &
% ps
  PID TTY          TIME CMD
11484 pts/5    00:00:00 a.out

ひとつのプログラムのなかに複数のスレッドが動ける。

これはシングルスレッドかつシングルタスク。


int main()
{
  std::cout << "hello thread" << std::endl;
  return 0;
}

これはマルチスレッドかつシングルタスク。


int main()
{
  thread th(  std::cout << "hello thread" << std::endl; );
  thread th2(  std::cout << "hello thread" << std::endl; );
  th.join();
  th2.join();
  return 0;
}

これはマルチタスク。


 % ./a.out &
 % ./a.out &
 % ps
  PID TTY          TIME CMD
 8668 pts/5    00:00:00 a.out
 8874 pts/5    00:00:00 a.out

結論

結局、わからん。

他人のコードに INCEPTION する!coursera で The Hardware/Software Interface を受けた

$
0
0

coursera で The Hardware/Software Interface を受けた感想です.

2014-08-29-211509_445x249_scrot.png

目的

組込みソフトの知識を身につけるため

私はいちおう組込みエンジニアなのだが, 組込みソフトの知識がない.

すごく, そのことに危機感を感じている. 組込みソフトの知識は, 実際に業務で取り組まないと身につける機会が少ない.

しかし, 仕事ではいつまで待っていても新しいプロジェクトには移動できな い.仕事を通して知識を身につけようなんて思っていたら, 10 年経っても身 につかない気がする.

メモリ管理・プロセス管理・アセンブラ言語などなど, このあたりの知識がほしい.

アセンブラ言語の知識を身につけるため

この講座では, アセンブラ言語についても学ぶことができる.

職場でも, アセンブラ言語を利用しているという話はたまにきくので, 学んでいれば, 新しい業務にもつながることを期待.

感想

C 言語のことをなにもボクは知らなかった

一番感じたことは, 自分は C 言語のことについて理解したつもりになってい たが, それはまだまだ不十分だったということだ.

たとえば, この講義では, malloc, free の原理について解説される. そして, malloc, free を自分で実装するような課題が出される.

ヒープ領域, スタック領域がどういう役割していて, それぞれどういうようにプログラムでは利用されているか, 自分は理解していなかった. それなのに, C 言語なんて全部わかったよ! なんて思っていた自分が恥ずかしい.

まるでそれはインセプション!

課題がどれも難しく, 毎週 10 時間以上かかった. しかし, 今まで受けてきた MOOC の課題の中ではもっともおもしろかった.

そのなかでもとくにおもしろかったのは, バッファオーバーフローについての課題.

与えられたプログラムのセキュリティホールに対して バッファオーバーフローアタックを仕掛けて, まったく関係ない関数を実行したり, さらにはセキュリティホールから自分で書いたアセンブラコードを注入し て実行させたりする.

それはまるで, 映画”インセプション” のような興奮だ!

映画では, ディカプリオが他人の夢の中に侵入して,思い通りの記憶を埋め込む. そして私は, 他人のプログラムのなかに侵入して, 思い通りのコードを埋め込む.

ハッカーはこの快感をもとめて悪さをするのだろう.

内容

シラバスからそのまま引用.

Topics:
    Number representation
    Assembly language
    Basics of C
    Memory management
    Operating-system process model
    High-level machine architecture
    Memory hierarchy
    Implementation of high-level languages

Number representation

ビット演算について学ぶ.

まず, 驚いたことは, if や while のような制御文は ビット演算でかけてしまうということだ.

C 言語なんて楽勝でしょと思っていたら, しょっぱなから出鼻を折られるという..

また, コンピュータは 0 と 1 の世界で, プログラミング言語はそれを置き換 えたものに過ぎないという, 基本的なことを気づかされる.

Assembly language

x86-64 アセンブリ言語の文法を学ぶ. 意外にネットや書籍での情報が多く, 参考になった.

昔のテレビゲームは, アセンブラ言語でかかれていたときく. こんな世界でガリガリコーディングをするなんて, すごいな.

Memory management

メモリがどのように利用されているかのお話.

プログラムがどうやって動いているのかをアセンブラレベルで理解して, 今までなにもわかっていなかったんだと自覚. とともに, 仕組みが分かって感動.

   2^n-1
   |---------------------|
   | Stacks              | ローカル変数, プロシージャの内容
   |                     |
   | Dynamic Data (Heap) | new や malloc で獲得できる領域
   | Static Data         | グローバル変数など.
   | Literals            | 文字列
   | Instructions        | プログラム. 関数
   |---------------------|
   0

Memory hierarchy

キャッシュアーキテクチャとその制御アルゴリズム, 仮想メモリについて. C 言語通じて, コンピュータアーキテクチャも学べる.

    | registers          |             |
    | L1 Cache           | SRAM        |
    | L2 Cache           | SRAM        |
    | Memory             | DRAM        |
    | local 2nd storage  | local disks |
    | remote 2nd storage | Web Servers |

私は, ストレージ屋だ. (そしてもうやめたい) キャッシュ技術を学ぶと, ストレージを支える技術というものは, かなりの部分がキャッシュが関わっているのだと思った.

  • Disk の性能をあげるためには?
  • ホスト I/O の性能をあげるためには?

とりあえず, 特許でこまったらキャッシュを思い出す. 講義でも, CS の世界での問題解決の常套手段が関節参照だ! と力説してた.

これから

今までセキュアコーディングなんてまったく意識したことがなかった. 無知のまま脆弱性をプログラムに仕込んでしまうことは恐ろしいと思った. もうすこし, セキュアコーディングについて学んでおこうと思った.

アセンブリ言語はこれ以上は深堀りしなくていいかな. . . なんとなくだけれども, プログラムの仕組みが理解できたし, あまりおもしろいものではないので.

Flycheck で g++ の日本語表記のコンパイルエラーがパースできていなかった (C/C++)

$
0
0

はじめに

Emacs の エラーチェッカーで flycheck がある.静的文法チェック. flymake の後継. cw – flycheck/flycheck

C++ でつかってみると, どうも動かないので調べてみたメモ.

Build-in

マニュアルによると, gcc, clnag, cppcheck が default のチェッカーとして用意されている.

パーサーを見てみると..

ソースを除いてみると, たとえば gcc のパーサーは以下.

(flycheck-define-checker c/c++-gcc
  "A C/C++ syntax checker using GCC.

Requires GCC 4.8 or newer.  See URL `https://gcc.gnu.org/'."
  :command ("gcc"

    "長いので途中省略"

  :error-patterns
  ((error line-start
          (message "In file included from") " " (file-name) ":" line ":"
          column ":"
          line-end)
   (info line-start (file-name) ":" line ":" column
         ": note: " (message) line-end)
   (warning line-start (file-name) ":" line ":" column
            ": warning: " (message) line-end)
   (error line-start (file-name) ":" line ":" column
          ": " (or "fatal error" "error") ": " (message) line-end))
  :error-filter
  (lambda (errors)
    (flycheck-fold-include-levels (flycheck-sanitize-errors errors)
                                  "In file included from"))
  :modes (c-mode c++-mode)
  :next-checkers ((warning . c/c++-cppcheck)))

おかしいなぁと悩むこと 1 時間近く… パーサーの文字が英語だと気づいた…

自分の環境では, g++ を走らせると,

  • error -> エラー
  • Warining -> 警告

と表示される.

日本語表記で checker を定義

しかたがないので, 自分で定義をする.

(require 'flycheck)
(add-hook 'c-mode-common-hook 'flycheck-mode)

(defmacro flycheck-define-clike-checker (name command modes)
  `(flycheck-define-checker ,(intern (format "%s" name))
     ,(format "A %s checker using %s" name (car command))
     :command (,@command source-inplace)
     :error-patterns
     ((warning line-start (file-name) ":" line ":" column ": 警告:" (message) line-end)
      (error line-start (file-name) ":" line ":" column ": エラー:" (message) line-end))
     :modes ',modes))
(flycheck-define-clike-checker c-gcc-ja
			       ("gcc" "-fsyntax-only" "-Wall" "-Wextra")
			       c-mode)
(add-to-list 'flycheck-checkers 'c-gcc-ja)
(flycheck-define-clike-checker c++-g++-ja
			       ("g++" "-fsyntax-only" "-Wall" "-Wextra" "-std=c++11")
			       c++-mode)
(add-to-list 'flycheck-checkers 'c++-g++-ja)

基本的なところにかなりハマってた…

システム制御は奥が深い! 井戸の中の蛙な自分.coursera で Cloud Computing Cocepts をうけた

$
0
0

はじめに

coursera で クラウドコンピューティングを学ぶ講座をとりました.

分量が多いので, Cloud Computing Concepts は Part1,2 に分かれている. 今回は, Part1 についての記事.

これは, クラウドコンピューティング 3 シリーズのなかのはじめに位置する講座です.

  • Distribute Systems
  • Cloud Application
  • Cloud Networking.

内容

内容は分散コンピューティングについての古典的な理論から, 最新の研究の話題まで, 幅広い.

Part1 では, 以下を学んだ.

  • Introduction

Clouds, Mapreduce, Key-value stores

  • Classical Precursors

Peer-to-ppeer systems, Grids

  • algorithms

Gossip, Membership, Paxos

  • Classical algorithms

Time and Ordering, Snapshots, Multicast

NoSQL や P2P の最前線の話題についても触れる.

動画がとても早口 (通常速度で x1.3-5 くらい?) あまり英語を聞き取れず. もっぱら以下の本の該当個所を読みながら進めた.

プロクラミングの課題もある. C++ で実装する.

感想

以前の仕事について

この記事とかぶる部分もあるが, もう一度.

今働いている会社の部署は, サーバやストレージ製品の制御ファームをつくっている. クラウドコンピューティングに関わる製品の設計開発だ.

そして自分はというと, 今でこそ名実ともに窓際族であるので 部署の仕事とまったく関係ない遊び人をしているが, かつてはストレージ製品の開発に関わってた.

自分の担当していた機能は, 異常検出.

2,4,8 ノードのそれぞれ独立した RAID コントローラが, それぞれを互いに監視しあう. あるコントローラで異常が発生したときは, 別のコントローラが異常をすばやく検出して, エラーリカバリを実施する.

なので, 以今回学んだことは前の仕事にかなり関わってた.

あまりに無知だった

8 ノードでの異常検出について自分の頭でいろいろ考えた.

自分の知らないところでは, そのような知識は体系化されて, 理論的な裏付けがされていて, 改良されていることなど, 想像だにしなかったことだった.これには, とても驚いた.

以下, 具体例をあげる.

Failure Detector/HeartBeating

Membership List

自分の関わってきた製品は, 最大 8 ノードまでだったが, 今後はノードが動的に追加できる, スケールアウト型ストレージの需要がでてくるかもしれない.

今までは, 固定の構成で仕様を考えていたが, 動的に変更されるような構成で仕様を考えることになるかもしれない.

スケールアウト型の制御方法で王道的な制御方法として MembershipList による制御があることをしった.

Consensus

Master-Slave アーキテクチャで制御しているとき, Master であるノードで異常が発生したさいに, 次の Master ノードを決定する必要がある.

また, 複数ノード同時に異常を検出した場合, 被疑個所がノードにあるの か通信経路にあるのかを決定して, たのノードと合意をとる必要がある.

このような, 複数のノード間で単一の結果について合意を得るプロセス は Consensus 問題と呼ばれていて, それに対して効果的なアルゴリズム の研究がされている.

システム制御は奥が深い! そして自分は井戸の中の蛙だった

自分の所属している部署は, 自称システム制御を得意としているが, それは井戸の中の蛙のような気がしてきた. いったい, なにと比較して得意だといっているのだろうか? 年月だけ重ねても, 世の中についていけなければ意味がない.

他のクラウド製品が, フォルトトラレント性を確保するために どのようなことをしているのか, まったく無知である. それらは企業秘密ということもあり, 特許で防衛しているところもある.

しかし, 世の中では, 分散コンピューティングの理論やアルゴリズムが 日進月歩で開発されていて, Yahoo, Google, Facebook などの先端企業は そのような技術を取り入れている.

新しい技術に対して無知であることは, 世の中からとりのこされるばかりか, 自分たちの仕事すらなくなってしまうおそれのある, 非常に危険なことだ.

継続して技術動向を追いかけていくような態度が必要だ. それは, 自分にも必要だが, 組織にも必要だ.

Viewing all 42 articles
Browse latest View live