いさぽん部屋(isapon.com)

ゲーム系プログラマによる特に方針のないブログ。技術系とカレー、ラーメンネタ多めだったはずが、最近はダイエットネタ多め。

moveされた右辺値の扱い

ふと、move後のオブジェクトの状態ってどうなんてんだっけ?と気になった。


仕様上ではムーブ後のオブジェクトは「書き換えてよい」となっているが、この場合の書き換えがどこまでの話なのかというのがちょっとわかりにくかったので、改めて勉強しなおし。


すっからかんになっているというのは解ってはいるんだけど……具体的にはどうなんだと。


コードに表すと、以下の時の a の状態はどうなんのか(というか、どう実装すべきなのか)ということ。


containor_type  a;
containor_type   b = std::move(a);

empty()やsize()は使える

下記の動画を見ると、ムーブされたオブジェクトは前提条件が必要な関数と不要な関数があり、前者は使ってはならないが後者は使えるということ。


www.youtube.com

ざっくり言うと「ステータスの確認はできるがそれ以外は保証しない」という感じだろうか?


つまり、コンテナで言うところの empty() や size() のようなは意図通りに使用できるが、push() だったり get() だったり at() だったりのような中身に触れるもの使用できない。


ムーブされた後のオブジェクトが使えるのかどうかくらいの判定はできる、もしくはできるようにしておけということっぽい。


先の例だと……

a.empty();  OK
a.size();  OK
a[i] NG
a.push_back() NG
a.find() NG

ということになる。 でも、これだと「書き換え」はできないよな……という気もしないでもない。

std::swap() ができるようにする

書き換えについての答えは std::swap にあった。STLのswapの中身は下のような感じだ。


template <typename T>
void swap(T& a, T& b)
{
    T c = std::move(a);
    a = std::move(b);
    b = std::move(c);
}

aもbも一度ムーブされているが、そのあとに operator = (T&&) で上書きされている。つまり、書き換えられているってことだ。


自分で実装する場合

基本的には std::move(my_class_obj_a, my_class_obj_b) が動くようにしておけばよい。


ムーブ後に呼ばれても良いように実装すべきものをまとめると次のような感じ。


必須となっているものは、オブジェクトがどのような使われ方をするにしても、必ず実装すべきもの。必須に近い推奨となっているものは、プライベートな型など利用法が限定的だったりわかっているものを除けば実装しておいたほうが良いもの。


関数 呼べるか 補足
デストラクタ 必須
operator = 推奨(必須に近い)
empty(), size() 推奨
clear() 推奨
operator ==, operator != 呼べる
operator ==, operator != 呼べる
initialize(), reset(), refresh() 呼べる よくある関数

あとは、次のように右辺値として連続で呼ばれても大丈夫なようにしておくくらいかな?


containor_type  a;
containor_type   b = std::move(a);
containor_type   c = std::move(a);

とりあえず迷ったときはムーブされたらデフォルトコンストラクタが呼ばれた状態まで戻しておくと良いです。


実機のログをコンソール(ターミナル)から見る

3回ほどハマったのでメモ。


NSLog を止めて os_log を使う

iOS10以降はログのシステムが変わったので、基本的にはNSLogを使うのではなくos_logというAPIを使います。そうしないと、現状では xcode のあの使いにくいコンソールログでしかログを確認できません。


使い方は簡単。os_log() という関数を呼び出すだけ。ただし、1点気を付けるのは "%s" ではなく %{public}s のように書きます。そうしないと、ログの出力時に のようになります(詳細は割愛)。


#import <os/log.h>
void log(const char* msg)
{
  os_log(OS_LOG_DEFAULT, "%{public}s", msg);
}

idevicesyslog を使う

idevicesyslog というコマンドは libimobiledevice というソフトウェアに含まれています。macosのHomeBrewを使ってインストールします。


brew update
brew upgrade
brew install usbmuxd --HEAD
brew install libimobiledevice --HEAD




インストールが終わったら


idevicesyslog




でログが見えます。

ログを成型する

idevicesyslog でログを見るとxcodeで見た時のように無駄に長ったらしいログが出ます。

Oct 18 13:27:21 devicename bundleid[710] <Notice>: hogehoge fugafuga

たぶん、見たいのは「hogehoge fugauga」の分だけ。そこで、sedを使ってログを成型。

idevicesyslog | sed -e 's/^.*<[A-Za-z]*>: //'

これで

hogehoge fugafuga

だけになります。あとは grep なりと組み合わせると、ログが見やすくなります。

NASのHDDが異常をきたした

自宅でDS916+というNASが稼働中なのだが、そろそろ埃が溜まってきているかと思い、神棚の掃除のついでにと一緒にハタキでパタパタしました。


DS916+には4TのHDDを3台+SSDのキャッシュ(読み取りを早くするための仕組み)していましたが、ちょいと前から容量不足のアラートが来ていたので、これを機にキャッシュをHDD に置き換え、容量拡張を行うことにしました。


が、容量拡張を行ったところ、トラブルが!?


今回はそんなトラブルのお話。


大切なデータ

俺の場合、とうとうプログラム歴が20年を超えましたが、20年前から今まで書いたプログラムのほぼ全てをこのNASに保管してあります。


旅行に行った時の写真や、遊びに行った時の写真なんかは全然、残していませんが(※1)、プログラムは残してあります。このプログラムたちが俺のアイデンティティと言えるほどです。


こうした、記録や思い出(?)は金では買えないものなので、無くなったら泣けるなんてものではないので、データを失わないようにしっかりと保存したいところです。


DS916+はこうした大切なデータを保存するための重要な装置なわけです。


※1)実際には写真はどこかに残ってると思う。……が、どこにあるかは分からないし、探す気もないので、実質無いに等しい

DS916+ ってなんぞや?

Synology社から発売(※1)されているNAS。↓こんなの(ただし、後続機)


最大4台のHDDを内蔵することができてRAIDを組むことができます。HDDも結局は機械なので、いつかは壊れてしまうことがあるわけですが、RAIDにしておくと1台壊れても復旧できるので、失いたくない大切なデータはRAID化されたHDDに保存しておくのがおすすめです。


また、DS916+はAmazon Cloud Storage や GoogleDrive、Microsoft OneDrive との同期機能も持っているので、NASに保存しつつ、クラウドサーバーにもバックアップということも可能です。


普段はDS916+に入っているので、すぐに取り出すことができるし「物理的に手元にある」という精神的安定感があります。


また、クラウドストレージだと、ちょいちょい値上がりしたり、容量が減ったりするし、肝心な時にネットワーク障害があったりしてデータを取り出せなかったりするような心配があるため、やっぱDS916+のように手元に物理的にあるのはメリットが大きいです。


とはいえ、火事や地震でDS916+そのものが壊れると怖いので、俺の場合は必要なデータはDS916+からクラウドストレージに定期的にバックアップを行っています。とはいっても、自動でバックアップしてくれているので、気にしたことはありませんけど(笑)


余談ですが、所謂「おたから(笑)」については、バックアップしてません。


※1)最近では後継機であるDS918+も発売されています。家庭で使う分にはDS916+でも十分な気もしないでも無いのですが、型落ちでもいいから少しでも安いほうが……というならDS916+でも良いのではないかと。

異常を検知した

DS916+は初期設定ではで半年に1回HDDに異常がないか全スキャンするようになっています(自分で設定すれば月1回とかも可能)。


次回のチェックは2か月後だったのですが、今回のHDDの増設でHDDのスキャンが入ったことで、HDDの異常が検出されました。


ちなみに異常が発見されるとメールを飛ばすようにも出来ます。


さて、ブラウザからDS916+の管理画面を覗いてみます。


f:id:no-operand:20180703082150p:plain

警告の文字が!今度はHDDの個別情報を見てみると、52か所でHDDに異常が出ています。


f:id:no-operand:20180703082200p:plain

これがRAIDではなかったら、52個くらいのファイル(フォルダ情報などが壊れていれば、フォルダ内全部が……ということも!?)が失われていたわけです。


クラウドストレージで怖いのは、同期をとる際に「壊れたファイルは消したファイル」として扱われることがあるということです。DS916+だと、その心配がないのがありがたい。


プログラムって、1ファイルでも壊れると、プロジェクトそのものが壊れると等しいので……


HDDの個別情報をさらに詳しく見てみます。


f:id:no-operand:20180703091706p:plain

今回トラブルが出たHDDは「52か所の異常があるけど、最大199か所まではなんとか動くよ、でも140か所を超えたら、もう、壊れる直前だぞ」と書いてあります。


言ってしまえば、まだ耐えられるわけですけど、HDDって「1度壊れ始めるとあっという間に壊れる」ので、早めにリプレイスをしたほうが良いですね。


そんなわけで、新しいHDDを注文し、届いたら入れ替え予定です。


関連商品

現行機種。HDDの最大搭載違いのモデルも選べます。バックアップできれば速度は気にしないというなら、少し安いDS218+やDS718+でも良いかと。




自分の使っているモデル。なぜかこちらのほうが高い……




HDDは2台以上使うこと。DS916+なら最初から3台以上を使うことをお勧め。


赤いHDDはNAS向け(24時間265日連続稼働向け)のもので、ちょっとお高めです。





青いHDDは連続で電源入れっぱなしには向いていませんが、DS916+なら夜になったら電源を落としたり、未使用時間が長ければHDDをスリープしたりできるので、家庭で使う分には安いものでもよいかなと。




昔は悪評の高かった「Seagate」というシリーズ。最近は悪くないらしいので、今度これを使ってみようかと思ってます。




iOS向けAdhocアプリをWEB経由で配信する

ちょっとハマったのでメモ。


iOS向けの開発をしていると、iTunesConnectやらAppleDevelopperCenterやら色々なところに飛ばされます。


もう、それだけで頭が禿そうになるのに、さらにそれをxcodeが無い人に向けて配信しようと思ったらTestflightにアカウントを登録して……など、もうこの上ないほどアカウントまみれでストレスがマッハです。Googleの開発し易さを見習っていただきたいものです。


と、いうわけで適当なサーバーにダウンロード用の窓口を作ってみます。今回はapacheを使う&動作テストと言うことで、深く考えないようにします。


WEBサーバーでの事前準備1(証明書)

まず、iOS向けアプリの配信をする場合はsslで接続できるようにしておく必要があります。加えて、自己著名でも良いので、改ざん防止のための証明書が必要です。


証明書をダウンロード(Aタグでリンクを張ればよいです)できるようにして、iPhoneからリンクを選べば証明書をダウンロードできます。ちゃんと検証済みになっていればOK。SANパラメータはなくてもOKです。


f:id:no-operand:20180521155230p:plain

WEBサーバーでの事前準備2(MIME)

.ipaファイルと、.ipaファイルを指定するための.plistファイルに対するMIMEの設定が必要です。とりあえず htaccess にでも書いておきます。


一応これで準備OKです。


AddType  application/octet-stream .ipa
AddType text/xml .plist

manifest.plist を作る

manifest.plistというテキストファイルを作成します。ファイル名は必ず「manifest.plist」にして下さい。


昔はファイル名は自由だったと思うのですが、最近のアップデートでmanifest.plist以外を受け付けなくなりました。ファイル名が違うと「無反応」で終わり、何が何だかささっぱりわからなくなります。


最小限の中身は下のような感じになります。https://foo.bar/hoge.ipaと書いてあるところはipaファイルのURL、com.isapon.hoge.fugaには、xcodeで設定したBundle Identiferを書きます。titleはとりあえず何でもよいのですが、無いとダウンロードできないので、てきとーに埋めておきます。


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>items</key>
    <array>
        <dict>
            <key>assets</key>
            <array>
                <dict>
                    <key>kind</key>
                    <string>software-package</string>
                    <key>url</key>
                    <string>https://foo.bar/hoge.ipa</string>
                </dict>
            </array>
            <key>metadata</key>
            <dict>
                <key>bundle-identifier</key>
                <string>com.isapon.hoge.fuga</string>
                <key>kind</key>
                <string>software</string>
                <key>title</key>
                <string>とりあえずなんでも良い</string>
            </dict>
        </dict>
    </array>
</dict>
</plist>

manifest.plist へのリンクを用意する

ダウンロードページに以下のようなリンクを張ります。


あとは、iPhoneからダウンロードページを開けばOKです。


<a href="itms-services://?action=download-manifest&url=https://foo.bar/manifest.plist">だうんろーど</a>

WSL Ubuntu 18.04 LTS をインストールしてみた

Microsoft Store に Ubuntu 18.04 という新しいパッケージ(というよりアプリというのだろうか?)が来ていたので、インストールしてみた。


Microsoft Store からインストール

Windowsのスタートメニューから「Microsoft Store」を起動し、検索ボックスで Ubuntu と入力。


古いUbuntuと新しいUbuntu(18.04)があるので、18.04を選びます。

f:id:no-operand:20180516220429p:plain

インストールできない

早速インストール…と思いきや、「入手」を押すと一瞬ダウンロードを開始したと思ったらすぐに終わり、いつまでたっても「入手」のまま。


いろいろ調べたら、一回サインアウトしてみると良いよと、Mictosoftのサポートページのどこかに書いてあったので、一度サインアウトします。


ウィンドウの右上にある自分のアイコンを選ぶと、アカウント切り替えメニューが出るので、その中から自分のアカウントを選択。その後「サインアウト」が出るはず。


f:id:no-operand:20180516221049p:plain

インストール完了後

Ubuntu18.04の場合は ubuntu1804 というコマンドで設定変更できます(Microsoft Store のアプリ説明欄に書いてあります。ここの説明文をクリップボードにコピーしたい今日この頃)。


f:id:no-operand:20180516221728p:plain

デフォルトのユーザーを変えたいならばコマンドプロンプトかPowerShellで次のようにします。


ubuntu1804 config --default-user USERNAME

ついでに、新しいユーザーにsudo権限を与えるときは、linux 内で

gpasswd -a USERNAME sudo

WSLの中で暮らすためのメモ

Windows10 RS4 アップデートで、WSL周りがかなり使いやすくなった。以前よりもさらにWSLとWindows間での連携がやりやすくなっています。


そんなわけで、WSLのメモ。


ちなみに、ターミナルエミュレータなどを使わずに、使い勝手がいいとは言えないが標準のDOS窓を使うのがトラブルが少なくてよい。

WSL(bash.exe)を起動する

起動時に、~ を引数として渡しておくと、ホームディレクトリから始まるので使いやすい。

C:\Windows\System32\bash.exe ~

WSLからバッチファイルを実行する。

cmd.exe に /c オプションを渡します。パスを指定するときはWindowsからパスで指定します。

cmd.exe /c c:\hoge\fuga.bat

バッチファイルをcmd.exeを指定せずに起動できるようにする。

binfmtで登録しておきます。

sudo sh -c "echo :WindowsBatch:E::bat::/init: > /proc/sys/fs/binfmt_misc/register"
sudo sh -c "echo :WindowsCmd:E::cmd::/init: > /proc/sys/fs/binfmt_misc/register"

WSLのファイルをWINDOWS側のパスに変換する

/bin/wslpath コマンドを使うとよい。aコマンドを外すと相対パスになります。wではなく、uを渡すとWSL内のパスになります。 w(indows), u(nix) と覚えるよいいかも?


$ /mnt/c/hoge/fuga
$ slpath -aw  foo.bar.txt
c:\hoge\fuga\foo.bar.txt

参考 wslpath has no "usage" or "help" information · Issue #2715 · Microsoft/WSL · GitHub

WSLからWindowsの実行ファイルを実行してみる

拡張子の .exe を忘れなければOK。

hoge.exe

ただし、これだと hoge.exe が終了するまでコンソールに戻ってこないのでGUIアプリの場合はバックグラウンド実行するとよい。やりかたは、コマンドの最後に & をつけるだけ。

hoge.exe &

試しにWSLからAndroidアプリをビルドしてみる。

※binfmtで.batを登録済み

cd /mnt/d/myproj
(cd android && ./gradlew.bat installDebug)

試しにWSLからVisualStudioのプロジェクトをビルドしてみる。

alias msbuild="/mnt/c/Program\ Files\ \(x86\)/Microsoft\ Visual\ Studio/2017/Community/MSBuild/15.0/Bin/MSBuild.exe"
cd /mnt/d/myproj/
(cd vcprj && msbuild)

WindowsからWSL内のファイルを操作する(今のところ禁止)

Windows10RS4の段階では、Windows側から直接操作してはいけません。というのも、Linuxのファイルシステムにはパーミッションだったり、ファイル名の大文字小文字の区別など、Windows(というかNTFS)のファイルシステムにはない情報が必要なため、VolFSというシステムを用いて裏でいろいろと行っています。 Windowsからファイルを操作するとこのVolFSとの情報にズレが出るため、おかしなことになります。


Microsoft Store からWSLをインストールした場合以下の場所に入っています。

C:\Users\USERNAME\AppData\Local\Packages\PACKAGENAME\LocalState\rootfs

※将来的にはWindowsからも気にせず操作できるようになるといいのになぁ。

アクアリウムと水耕栽培の現状

観賞魚の入った水槽の上部にあるろ過装置。


ここに野菜を植えて、完全自己完結の有機水耕栽培を目指してから幾分が過ぎました。


結論から言えば「うまくいく」で間違いないかと思います。


シソが育った

f:id:no-operand:20171123124723j:plain

写真で堂々とそびえたつ枝はダイソーで買ったシソの種から育てたシソです。これは全盛期である11月くらいのもので、花が咲き始めたころのものです。


ちなみに夏頃から冬の間はほぼ毎日(たまに飽きて食べなかった日もありましたが)シソを収穫し、食べ続けることができました。


f:id:no-operand:20180409151420j:plain

現在はシーズンを終え、すっかり枯れてきました。シソ自体は1年草なので、冬越えは出来ませんでしたが、しっかり種を回収することができました。


そんなわけでして、水換え不要で肥料も不要と、まったく手間がかからないのでアクアリウム+水耕栽培は可能だというのが俺の結論です。


ちなみに枯れたシソの手前にあるのは、この後シソを処分し代わりに育ててみるつもりの「ブロッコリー」「長ネギ」「ニンジン」「バジル」です。全部スーパーで買った野菜を再生させています(笑)


反省点

基本的になんでも育つと思いますが、育てる野菜(植物)の選定が必要かなと。


避けたほうが良いものは次の通り。


1. 根菜

たぶん育つと思いますけど、今回のようにろ過装置(上部フィルター)を使う場合はそれほど栽培装置が物理的に大きくないので、混載だと育てるだけのスペースが足りません。


根菜とまでは言いませんが、ミョウガも厳しかったです。葉は出ますが、あの食べられる部分が育つ物理スペースがなくただただ葉を眺めるだけになってしまいました。


逆に言えば、水耕栽培装置部分の大きささえ確保できればアリだと思います。


2. 枝が生えるもの

今回のシソもそうですが、枝が生え幹がしっかりするものは避けたほうが良いと思います。


というのも、育ちすぎて倒れそうになるし、ものすごく値を這わせるのでほかの植物や野菜が一切育たなくなります。


実際にシソが育ち始めるまでは色々な野菜の芽が出ていたのですが、シソが育つにつれてすべて全滅しました……


3. ハーブ類

シソも該当しますが、ハーブ類はほかの植物の成長を阻害する成分を出すので、シソ同様にほかの植物が育たなくなると思います。


ミントなどがほかの植物を枯らしていくのは有名ですね。


わかったこと

基本的に普通の水耕栽培と同じ。


肥料については魚の餌→魚の糞→バクテリアが分解で賄える。


新しい挑戦

  1. 再生野菜を育ててみる。
  2. 今回はアクアリウムに水耕栽培を追加したが、水耕栽培装置をベースにアクアリウムの要素を組み込んでみる。