altebute.hatenablog.com

犬も歩けば規格にあたる

PushbulletのPortalが凄いかも知れない。

PCとAndroid端末をWEBを介して接続し、様々なプッシュ通知を行うサービスを提供しているPushbulletが、新しいアプリPortalをリリースした。

Pushbulletでは、Androidに届いた通知を、PC側のブラウザの拡張機能を用いて、GoogleクラウドメッセージングサービスやAppleのプッシュ通知サービスを介して受け取ったり、小さなファイルを転送する事ができた。*1

Portalでは、(恐らくは同様の方法を用いて)ブラウザのみで認証を行い、Android側にファイルを転送する事が出来る。この際、認証によって、同じLAN内にある時のみ接続を確立し、ファイルの転送はLAN内で行われる。

このため、Pushbulletとは異なり、サイズの大きいファイルも転送する事が出来るほか、WEB上にファイルをアップロードし、パブリックなURLを介して転送を行う必要が無く、よりセキュアかつ高速だ。

利用方法も簡単だ。

  1. Android側にアプリケーションをインストールする。
  2. PC側で portal.pushbullet.com を開く。
  3. 表示されたQRコードAndroid側で読みとり、認証、接続を確立する。
  4. ドラッグ&ドロップでファイルを転送する。

フォルダや、複数ファイルを同時に転送するにはPC側でChrome拡張をインストールする必要があるようだ。

Pushbulletはセキュリティに関しても見やすい位置にきちんと表示しているので、心配な人はそこを見るといいだろう。個人的になWEBを介した認証を行うとLAN内での接続が確立される仕組みが気になる所だ。

更に現在ベータテスター募集も行っているようだ。*2

*1:これらの仕組みはSeculityのページに書かれている。

*2:Introducing Portal

RAR for Androidが素晴らしい件

Android上でzipアーカイブを解凍するためにRAR for Androidを導入したのだが、これが素晴らしかった。

Android向けのアーカイブの解凍アプリは多数あるが、RAR for Androidの特筆すべき点はアーカイブ内にパスに日本語を含むファイルも文字化けを起こす事無く解凍出来る点である。

WinZipではディレクトリ構造もファイル名も完全に壊れ、ファイル自体も破損してしまい(単に壊れたパスだったから対応するソフトがファイルアクセスに失敗しただけかも)使い物にならなかった。

次に気に入っている点は、RAR for Androidがファイラの機能を内蔵する事だ。ファイラは多くの権限を要求するため、その扱いには細心の注意を要するが、RARLABは老舗であり、個人的にはESファイルエクスプローラーのES APP Groupや、アストロファイルマネージャーのMetago等よりも信用出来る(あくまでも比較的、という話だが)。

Windows 10 Insider Previewで、コマンドプロンプトでフォントが異常に小さくなった時の対処法

原因

MS ゴシックがインストールされていないのが原因です。最初にインストールしたWindows 10が英語版だからなのか否かは不明です。

対処法

  1. 使用したいフォントをインストールする
  2. レジストリを編集する
  3. コマンドプロンプトの設定でフォントを選択する

という手順で直せます。

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Console\TrueTypeFont

を開き、932. 932.. 932.1 932.2等の名前で文字列値を追加し、使用したいフォント名をいれましょう。私のお勧めはIPAゴシック、サイズは17です。

コマンドプロンプトの設定で一覧に無いサイズを選択する場合は、直接入力してからフォント名をクリックし、その後再度サイズをクリックし直す必要があるようです。

残念ながら、ttfのみ対応で、otfには対応しないようです。

サイズによって正常に動作したりしなかったりするみたいです。

  • OK
    • 6
    • 8
    • 10
    • 12
    • 14
    • 24
    • 28
    • 36
  • NG
    • 16
    • 18
    • 72
    • 20

参考

niconicoがAndroidのバッテリードレインを引き起こす件について

ニコニコ生放送Androidで見るために公式アプリであるniconicoを使っているのだが、こいつがバッテリードレインを引き起こしていた。

事の経緯

  1. 電池の履歴の詳細を見て、使っていない時も常にスリープになっていない事に気付く。
  2. twitterの同期とtwitcle plusの自動更新を疑うも、改善されず。
  3. niconicoのプッシュ通知を切ったら改善された。

詳細

niconicoのプッシュ通知は、ユーザー、チャンネル、コミュニティーの動画投稿や生放送開始を通知してくれるが、この機能はニコニコ動画のサーバーと常時接続し、通信を監視する事で成り立っている。

そのため、有効になっている間はスリープにならず、バッテリーを消費し続ける。

幸いniconicoのプッシュ通知には時間指定の設定があるので、完全にオフにはせずそちらの設定を用いてもよい。

規格で学ぶ、例外と未定義の動作

例外周りを今まできちんとやってこなかったので、ちょいちょい調べたところ、日本語のWEB上の情報だけでは足りなかったので、規格にあたった。

戻り値を戻さない制御

以下のプログラムは多くのコンパイラで警告を発する。

int f(){}
int main(){}

理由は関数fが戻り値を戻さないからだ。戻り値の型がvoidの場合は問題ないが、戻り値を伴う関数戻り値を戻さかった時、その動作はundefined behaviorとなる。main関数においては、return 0;を意味する。

6.6.3 The return statement 2 ... Flowing off the end of a function is equivalent to a return with no value; this results in undefined behavior in a value-returning function. ...


2 ... 関数の末尾に到達する事は、値を伴わないreturnと等価である。これは値を戻す関数においては、未定義の動作を引き起こす。 ...


3.6.1.5
A return statement in main has the effect of leaving the main function (destroying any objects with automatic storage duration) and calling std::exit with the return value as the argument. If control reaches the end of main without encountering a return statement, the effect is that of executing

return 0;


main内のreturn文はmain関数からの離脱を意味し(自動変数の寿命を持つあらゆるオブジェクトを破棄する)、std::exitを戻り値を引数として呼ぶ。もし制御がreturn文に遭遇する事無くmainの末尾に到達した場合、return 0;が実行される。

尚、clangやgccでは警告は出るがビルドは通る。文法上はwell-formedだからだ。VC++では強い警告時はデフォルトではビルドが通らないので、ビルドエラーになる。

int f(){ throw 0; }
int main(){ f(); }

簡単のため、送出する例外の型はintにしている。上記のコードでは、例外がcatchされず関数fを離脱する。

15.1 Throwing an exception ... 2 When an exception is thrown, control is transferred to the nearest handler with a matching type (15.3); “nearest” means the handler for which the compound-statement or ctor-initializer following the try keyword was most recently entered by the thread of control and not yet exited.


2 例外が創出された時、制御は最も近い適合する型のハンドラに転送される。「最も近い」とは、最も最近スレッド制御が突入し、まだ終了していないtryに続く複合文またはメンバイニシャライザを意味します。 15.3 Handling an exception ... 9 If no matching handler is found, the function std::terminate() is called; whether or not the stack is unwound before this call to std::terminate() is implementation-defined (15.5.1).


もし適合するハンドラが見つからなかった場合、std::terminateが呼ばれる。スタックがstd::terminateへの呼び出し前に巻き戻されているか否かは実装定義である。

main関数の末尾まで制御が転送され、std::terminateが呼ばれる。スタックが~云々の件はよくわからない。教えて強い人。

try-block

前述の規格に基づく例外が送出された際の制御の転送の例。

int f()
{
    try{ throw 0; }
    catch( int e ){ /* 最も近いハンドラでキャッチされる */ }
}
int main()
{
    try{ f(); }
    catch( int e ){ /* ここではキャッチされない */ }
}
int f(){ throw 0; }
int main()
{
    try{ f(); }
    catch( int e ){ /* ここでキャッチされる */ }
}
int f(){ throw 0; }
int main()
{
    try{ f(); }
    catch( char e ){ /* 型がマッチされないのでキャッチされない */ }
}
// ここで std::terminate が呼ばれる

function-try-block

以下のような型について考える。

struct inner
{
    inner(){ throw 0; }
}
struct outer
{
    inner m_inner;
   outer(){ /* この時点で m_inner のインスタンス化は終了している */ }
}

outerインスタンス化した時、メンバ変数m_innerインスタンス化の際に例外が送出される。この例外をouter::outerでキャッチしたいが、通常のtry-catch-blockではキャッチ出来ない。メンバ変数のコンストラクタの呼び出しはコンストラクタの内部に入った時点で終了しているからだ。

そこで、C++にはfunction-try-blockと呼ばれる構文が用意されている。

struct outer
{
    inner m_inner;
    outer()try{}
    catch( int e ){ /* ここで例外をキャッチする。ついでに再送出する。 */ }
}

コンストラクタやデストラクタでfunction-try-blockを用いて例外をキャッチした時、そのままハンドラの末尾に到達した場合、その例外は再送出される。

15 The currently handled exception is rethrown if control reaches the end of a handler of the function-try-block of a constructor or destructor. Otherwise, a function returns when control reaches the end of a handler for the function-try-block (6.6.3). Flowing off the end of a function-try-block is equivalent to a return with no value; this results in undefined behavior in a value-returning function (6.6.3).


15 もしコンストラクタまたはデストラクタのfunction-try-block内のハンドラの末尾に制御が到達した場合、ハンドル中の例外が再送出される。それ以外の場合、制御がfunction-try-block内のハンドラの末尾に到達した時、関数はreturnする。function-try-blockの末尾に到達する事は、値を伴わないreturnと等価であり、これは値を戻す関数においては未定義の動作を引き起こす。

末尾に到達しなかった場合、例外は再送出されない。以下のように記述した場合だ。

struct outer
{
    outer()try{}
    catch( int e){ throw 1; }
}

末尾に到達する前に別の例外を送出しているので、キャッチした例外は再送出されない。尚、コンストラクタfunction-try-block内のハンドラ内ででreturn文を記述する事はill-formedである。

14 If a return statement appears in a handler of the function-try-block of a constructor, the program is ill-formed.

デストラクタではどうなのかは良くわからない。そもそもデストラクタ内で例外を送出すること自体が推奨されない(ここでは言及しないのでぐぐられたし)。

function-try-blockコンストラクタやデストラクタだけでなく、通常の関数でも使用できる。

void f()try{ throw 0; }
catch( int e ){}
int main(){ f(); }

コンストラクタやデストラクタでないので、例外は再送出されない。その代わり、値を伴わないreturn;を意味する。つまり、次のコードと等価である。

void f()try{ throw 0; }
catch( int e ){ return; }
int main(){ f(); }

コンストラクタではないので、ハンドラ内でreturnしてもよい。

値を戻す関数の場合は以下のように記述する。

int f()try{ throw 0; }
catch( int e ){ return 1; }
int main(){ f(); }

上記のコードでは例外は関数fの内部で処理され、f1を戻す。main内に例外は波及しない。ただし、以下のコードは未定義の動作を引き起こす。

int f()try{ throw 0; }
catch( int e ){}
int main(){ f(); }

int型の戻り値を戻さなければならないのに戻していないからである。

ところで

Flowing off the end of a function-try-block is equivalent to a return with no value; this results in undefined behavior in a value-returning function (6.6.3).

上記の記述は"Flowing off the end of a handler of function-try-block"じゃないの?と思うのだがどうなのだろうか。教えて強い人。

他にも

  • 静的グローバル変数や、任意のクラスの静的メンバ変数のコンストラクタやデストラクタが例外を送出するとどうなるのか
  • ある構造体やクラスのメンバ変数のデストラクタが例外を送出した時どうキャッチするのか

等の問題があるが、規格書を全部翻訳する余裕は無いので自分で読んでほしい。

Boost.Multiprecision と BBP formula を用いて整数演算のみで円周率を近似する。

前回の記事で boost を導入したので、 Boost.Multiprecision と BBP formula を用いて整数演算のみで円周率を近似してみた。

整数演算のみなので、如何なる実行環境でも同じ結果が得られる筈。
cpp_rationalcpp_intが内部的に浮動小数点演算を使用していたら同じ結果は得られないが、そんなことは無いだろう。たぶん。

#include <iostream>
#include <boost/multiprecision/cpp_int.hpp>

boost::multiprecision::cpp_int power(int m, unsigned int k)
{
    boost::multiprecision::cpp_int result = 1;

    while (k--)
    {
        result *= m;
    }

    return result;
}

boost::multiprecision::cpp_rational bbp_formula(unsigned int precision)
{
    using cpp_rational = boost::multiprecision::cpp_rational;

    auto f = [](int k) -> cpp_rational
    {
        cpp_rational a(4, 8 * k + 1);
        cpp_rational b(2, 8 * k + 4);
        cpp_rational c(1, 8 * k + 5);
        cpp_rational d(1, 8 * k + 6);

        return (a - b - c - d) / power(16, k);
    };

    cpp_rational result = 0;

    for (unsigned int i = 0; i < precision; ++i)
    {
        result += f(i);
    }

    return result;
}

int main()
{
    using namespace std;

    for (int i = 0; i < 10; ++i)
    {
        auto result = bbp_formula(i + 1);
        cout << fixed << setprecision( 16 ) << result.convert_to< double >() << "(" << result << ")" << endl;
    }
}
3.1333333333333333(47/15)
3.1414224664224664(102913/32760)
3.1415873903465816(615863723/196035840)
3.1415924575674357(357201535487/113700787200)
3.1415926454603360(16071212445820879/5115625817702400)
3.1415926532280878(40413742330349316707/12864093722915635200)
3.1415926535728809(4318127540987083098959311/1374502686106089789849600)
3.1415926535889724(16331158360096799798177512637/5198369158853231585211187200)
3.1415926535897523(2090388270092909093421859664191/665391252333213642907031961600)
3.1415926535897913(64251934196540737654784844866951/20452025861189303550405613977600)