Hatena::ブログ(Diary)

SYNjuku-ACKihabara このページをアンテナに追加 RSSフィード

2015-01-22

[] Member class constructor is called from the initializer of the class

Class B's initializer has two parameters, which also can be used as class A's constructor parameter.

#include <iostream>

using namespace std;

class A {
    int a_;
    char* b_;
    public:
    A(int a, char* b) : a_(a), b_(b) {}
    void print() { cout << a_ << " " << b_ <<endl; }
};

class B {
    A a_;
    public:
    B(int a, char* b) : a_(a, b) {}
    void print() { a_.print(); }
};

int main() {
    B b(1, "abc");
    b.print();
    return 0;
}

2015-01-21

[] Apply string size limit to stringstream

#include <iostream>
#include <sstream>
#include <fstream>
#include <streambuf>
#include <stdint.h>

template <class CharT, class Traits=std::char_traits<CharT> >
class basic_hg_stringbuf : public std::basic_stringbuf <CharT, Traits> {
    uint32_t _limit;
    uint32_t _current;
public:
    basic_hg_stringbuf() : std::basic_stringbuf<CharT, Traits>(), _limit(50), _current(0) {}
    std::streamsize xsputn(const char* s, std::streamsize n) {
        std::streamsize ret = 0;
        if (_limit > _current) {
            _current += n;
            ret = std::basic_stringbuf<CharT, Traits>::xsputn(s, n);
        }
        return ret;
    }
};

typedef basic_hg_stringbuf<char> hg_stringbuf;

int main() {
    hg_stringbuf string_buf;
    std::ostream os(&string_buf);
    os << "0123456789" << std::endl;
    os << "0123456789" << std::endl;
    os << "0123456789" << std::endl;
    os << "0123456789" << std::endl;
    os << "0123456789" << std::endl;
    os << "0123456789" << std::endl;
    std::stringstream ss;
    ss.std::ios::rdbuf(&string_buf);
    while (!ss.eof()) {
        std::string line;
        std::getline(ss, line);
        std::cout << line << std::endl;
    }
    return 0;
} 

Output

$ ./stream
0123456789
0123456789
0123456789
0123456789
0123456789

[] Apply string size limit to stdout

template <class CharT, class Traits=std::char_traits<CharT> >
class basic_hg_streambuf : public std::basic_streambuf <CharT, Traits> {
    uint32_t _limit;
    uint32_t _current;
public:
    basic_hg_streambuf() : std::basic_streambuf<CharT, Traits>(), _limit(50), _current(0) {}
    basic_hg_streambuf(const std::basic_streambuf<CharT, Traits>& stream) : std::basic_streambuf<CharT, Traits>(stream), _limit(50), _current(0) {}
    std::streamsize xsputn(const char* s, std::streamsize n) {
        std::streamsize ret = 0;
        if (_limit > _current) {
            _current += n;
            ret = std::basic_streambuf<CharT, Traits>::xsputn(s, n);
        }
        return ret;
    }
    int overflow(int c = EOF) {
        if (c != EOF) {
            fprintf(stdout, "%c", c);
            return c;
        }
        return EOF;
    }

};

typedef basic_hg_streambuf<char> hg_streambuf;

int main() {
    hg_streambuf buf;
    std::streambuf* old = std::cout.rdbuf(&buf);
    std::cout << "0123456789" << std::endl;
    std::cout << "0123456789" << std::endl;
    std::cout << "0123456789" << std::endl;
    std::cout << "0123456789" << std::endl;
    std::cout << "0123456789" << std::endl;
    std::cout << "0123456789" << std::endl;
    std::cout.rdbuf(old);
    return 0;
}

Don't forget to restore the saved default value of std::cout, otherwise program will crash.

Output

$ ./stream
0123456789
0123456789
0123456789
0123456789
0123456789

2011-04-09

[][] yaml-cpp 0.26 traverse()

yaml-cpp 0.26 から型の扱いが変わったみたいなので

便利なtraverse()を書き直してみました。

以前までのtraverse()はここ(traverseで検索してください)をご覧ください。

void traverse(const YAML::Node &node, unsigned int depth)
{
	 YAML::NodeType::value type  = node.Type();
	 std::string indent((size_t) depth, '\t');
	 std::string out;
	 switch(type) {
	 case YAML::NodeType::Scalar:
		 node >> out;
		 std::cout << indent << "Scalar: " << out << std::endl;
		 break;
	 case YAML::NodeType::Sequence:
		 std::cout << indent << "Sequence: " << out << std::endl;
		 for (unsigned int i = 0; i < node.size(); i++) {
			 const YAML::Node & subnode = node[i];
			 std::cout << indent << "[" << i << "]" << std::endl;
			 traverse(subnode, depth+1);
		 }
		 break;
	 case YAML::NodeType::Map:
		 std::cout << indent << "Map: " << out << std::endl;
		 for (YAML::Iterator i = node.begin(); i != node.end(); i++) {
			 const YAML::Node &key = i.first();
			 const YAML::Node &value = i.second();
			 key >> out;
			 std::cout << indent << "Key: " << out << std::endl;
			 std::cout << indent << "Value: " << std::endl;
			 traverse(value, depth+1);
		 }
		 break;
	 case YAML::NodeType::Null:
		 std::cout << indent << "(empty)" << std::endl;
		 break;
	 default:
		 ;
	 }
}

以前までどおり YAML::CONTENT_TYPE type と宣言したときに

そんなものないよってなったので、わざわざソース読みましたが

リリースノートに書いてありますね。

ちゃんとドキュメント嫁ってことですね。

2011-03-26

[][]c++のstringでtcharを使う

#include <string>
#include <iostream>
#include <tchar.h>

typedef std::basic_string<TCHAR> tstring;
typedef std::basic_stringstream<TCHAR> tstream;

#ifdef _UNICODE
#define tcout wcout
#else
#define tcout cout
#endif

void _tmain(int argc, TCHAR **argv)
{
    tstring name(_T("hoge"));
    std::tcout << _T("tstring: ") << name << std::endl;
}

結果
tstring: hoge

[][]逆引きwindbgリファレンス(未完)


ステップ実行のたびにレジスタ一覧が表示されるのを消す

解法

Set Source Option コマンドを使う

l+o
説明

l+oはHides all message


CR4レジスタとかのほかのレジスタもrコマンドで表示したい

解法

Register Mask コマンドを使う

rm
rm <mask>
説明

rm で現在の Register Mask を確認できる

デフォルトは0x9

CR4レジスタを追加したいときは

rm 29


逆アセンブルしたときの表示行数をもっと増やしたい

解法

lパラメータで表示行数を指定する

u <addr> l20
u <addr> l-10
説明

値としてマイナスを渡せる

上はaddr以降を20行表示

下はaddrより前を10行表示


参考にしたもの

Windbgのヘルプ(F1で見れるやつ)


(追記)

こういうのはwikiとかにしてみんなで編集できるほうが望ましいので

これ以上更新はありません。たぶん

2010-10-31

[][]アクティブページレジスタ(Active Page Register)について

Lions’ Commentary on UNIX読書会に行ってきました。

6章以降を読み進めるのに、アクティブページレジスタのことを知っていたほうが

いいかなと思ったのでまとめてみました。


説明するにあたってのルール

この記事では、0始まりの数字0200などは8進数とします。

それ以外は10進数です。


基礎知識

メモリはページという単位で管理されていて

1ページは最大128ブロックで構成される。

1ブロックあたりの大きさは64byte

f:id:hon53:20101101002007j:image

詳しくはLions本の第2章を読んでください


仮想アドレスと物理アドレスの対応

とりあえず、仮想アドレスを物理アドレスに変換するためには

2つのレジスタを使うということを覚えておいてください。


Active Page Register(APR)

んでその2つのレジスタがActive Page Registerを構成している

Page Address Register(PAR)とPage Description Register(PDR)です。

それぞれ以下のような構造になってます。

f:id:hon53:20101101002006j:image

Page Address Register(PAR)

PARはPage Address Field(PAF)という

フィールドを持っていて、これは物理アドレスの開始位置からのブロック番号を

示します。また、物理メモリ上の開始位置も示します。


たとえば、Lions本の第6章のm40.sではPARを

0,0200,0400...に設定しています。

0200は0200番(ブロックは0始まり)のブロックを指します。

この領域の開始位置の物理アドレス

128*64=8192

8進で020000となります。


Page Description Register(PDR)

PDRは4種類のフィールドを持っています。

Access Control Field(ACF)

Access Information Bits(W)

・Expansion Direction(ED)

・Page Length Field(PLF)


ここではACFとPLFを取り上げます。ほかのフィールドについては

PDP11のマニュアルを参照してください。


ACFはAPRが指す物理アドレス上の領域のアクセス権を決めます。

00 の場合は すべてのアクセスを禁止

01 の場合は 書き込みを禁止

10 の場合は すべてのアクセスを禁止

11 の場合は 読み書きを許可


PLFは領域のサイズをブロックの数で示します。

実際の数はEDの値によって変わってきます(マニュアル参照)


以上を踏まえて、第6章のstart(0612)で行われていることを

見ていきます。

最初の6個のカーネルアドレスレジスタ

PARは0,0200,0400...に設定されます。これは前述の通りです。

PDRは077406に設定されます。これを2進数に直すと

111111100000110

になります。

ACFとPLFのすべてのビットが立っていることがわかります。

そのため、これらのカーネルアドレスレジスタ

読み書き許可で、

0200の場合は物理アドレス020000から

128ブロック分の領域を指します。


仮想アドレスを物理アドレスに変換

仮想アドレスは

15ビット目から13ビット目までがAPRの番号を指します。

12ビット目から6ビット目までがブロックの番号

5ビット目から0ビット目までがブロックのオフセット

となります。

該当のAPRから物理メモリ上の開始位置を調べて

ブロック番号とオフセット

物理アドレスを特定します。


参考

PDP11/40 Processor Handbook


その他

間違っている部分やわかりにくいところがあれば

指摘してもらえると助かります