startコマンドとスペースの相性

昨日のstartコマンドについて、さらに問題が起きたので追記。
というのも、よくある「コマンドとスペースの相性が抜群に悪い」ということです。
ただ、それにしても、startコマンドは非常に奇妙な動きをしたので、まとめ。


当然ながら、以下の呼び出しはエラーになります。

start C:\Program Files\Hoge\Hoge.bat

Program と Filesの間の空白でコマンドが区切られてしまうからです。
では、以下のように変えてみましょう。

start "C:\Program Files\Hoge\Hoge.bat"

空白を含むパスのために、二重引用符で囲みました。一見大丈夫そうです。
しかし、これも実はダメなのです。
startコマンドは、新規で作るコマンドプロンプトのタイトルが設定できます。
それが、""で囲った最初のテキストになるのです。


つまり、上の命令は、肝心のコマンドがタイトルの指定になってしまいます。
ということで、以下になります。

start "Hoge" "C:\Program Files\Hoge\Hoge.bat"

なんでもいいんですが、タイトルを付けます。
すると、二つ目の二重引用符は無事コマンドになるのです。


と、これだけで解決すればよかったのですが……。
実は、さらに問題は隠れています。バッチ処理、引数、渡したい時ありますよね?
その引数に空白があったらどうしましょうか、当然こうするでしょう。

start "Hoge" "C:\Program Files\Hoge\Hoge.bat" "C:\Program Files\Hoge\Foo.txt"

これは、実はエラーになります。
困ったことに、startが「"C:\Program Files\Hoge\Hoge.bat" "C:\Program」をコマンドとして認識してしまうのです。
バグなんじゃないか、、、とすら思うんですが、こういう挙動になってます。


つまり、コマンド・その引数、両方にスペースがある場合、そのままではどうやってもうまく行かないのです。
では、諦めるしか無いのでしょうか?
そんなことはありませんでした。

for %A in (C:\Program Files\Hoge\Hoge.bat) do start "Hoge" %~sA "C:\Program Files\Hoge\Foo.txt"

for構文を使います。
forを使うことで、コマンドを一度引数に取り込み、パス修飾「%~s」でショートネーム(8.3形式)にするのです。
そうすれば、コマンドには空白は含まれない安全なパスになります。


そして、幸運なことにコマンドがちゃんと空白なしで渡せれば、引数は二重引用符で囲っていても問題ありません。
(このあたりの仕様の微妙さは、若干不安が残りますが……)
結果、非常に面倒になりましたが、どのパスに空白があっても、なんとか問題なく実行できるようになりました。


それにしても思うのです。
なんで、こんなに空白に弱いのに、パスに空白を含めることを許可した上、
システムが作るフォルダに空白があるのか(Program Files)。
このあたりは、もうちょっとシステム的にサポートして欲しいと感じるものです。

スレッドとコンソール

よく面倒な繰り返し作業は、perlで書いて自動化しているのですが
このたび、どうしたらいいものか、という問題がひとつ。


お仕事を探して、それらを全部Thread::QueueにEnqueueして
Queueが空っぽになるまで、スレッドでお仕事を行ってもらう。
ただ、それだけのことだったのですが、そのお仕事(バッチ処理)の出力が
全部同じperlを実行したコンソールに出力されてしまうという……。


別に、ただの結果のアウトプットなので混ざってても別にいいのですが
もしできるならば、コンソールを複数出しておきたいなぁ、とか思ったり。
そういうことって、できるのかなぁ、と探してみたけど直ぐには見つからず。


んー、ユニークな名前でファイル作って出力しておくのが妥当かなぁ。
なにかお手軽な方法がないものでしょうか。

新規コンソール

スレッドとコンソールという前回の日記にて、スレッドで複数バッチ処理を起動すると、
コンソールへの出力が混ざってしまって……。
という話をしていましたが、あっさり解決したので、そのことに関して。


単純にコマンド「start」を使う。それだけでした。
startは、新規コンソールにてコマンドを実行するコマンドです。
/wait オプションにて、処理終了まで呼び出し側に処理が戻らないので、それも利用します。

use threads;
use Thread::Queue;

$thread_queue = Thread::Queue->new();

$thread_queue->enqueue(1);
$thread_queue->enqueue(2);
$thread_queue->enqueue(3);
$thread_queue->enqueue(4);


my $thd1 = threads->create(\&proc, "One");
my $thd2 = threads->create(\&proc, "Two");

$thd1->join();
$thd2->join();

sub proc {
  while(0 < $thread_queue->pending) {
    if( my $data = $thread_queue->dequeue ) {
      if( my $pid = fork() ) {
        threads->yield();
        wait();
      }
      else {
        exec 'start "Title" /wait wait.bat 2';
      }
    }
  }
}


こんな感じで、呼びだすといい感じになってくれました。
コマンドを未だにちゃんと把握しきれていないのは勿体無いな、と思いました。
ちゃんと勉強しないとダメですね。

グラフィカルに

私は、そろそろiPhone4を買おうかと、悩んでいる頃なのですが。
そんな折に、Androidに面白そうなのが登場。
App Inventor


子供向けの教育系でグラフィカルな言語は見たことがあるけど
ちゃんとしたツールやゲームを作れるものとしての言語というのは
見たことが無かっただけに驚きです。

グラフィカルなプログラミング言語というと、
ぱっと「宇宙のステルヴィア」のプログラムが浮かぶ、そんな私。


しかし、チュートリアルを見る限りでは……いくらグラフィカルになっても
当たり前ながらプログラムとしての「構造」は最低限必要なようで。
むしろ、規模が大きくなると、かえって見通しが悪くなるのではないかという懸念が……。

また、末端の修正はいいですが、繋がったピースの真ん中付近を変える時は面倒なのでは?
と感じてしまったりするけど、その辺はどうなんでしょうか。


とはいえ、面白そうなのは間違いないですね。触ってみましょう。

踏み出しの一歩

はじめまして。Mizuki(mizuki-astral)です。
はてなを、今更ですがはじめてみようと思います。
プログラム(主にC++)をメインに、たまに趣味のこと(ゲームや書籍)も書いていきます。

      • -

どんな事も、最初の一歩が一番緊張するものです。
今、この瞬間が一番緊張してます。
私は、ちょっとしたことでも緊張してしまうのです。

ちゃんと続くだろうか。
そもそも、何か書いて意味があることが書けるだろうか。
いろいろ不安はありますが、可能な限り毎日の更新を目指して行きたいと思います。

それでは、よろしくお願いします。

_SECURE_SCLによる差

_SECURE_SCLは、チェック付きイテレータ用の定義シンボルです。
STLvectorやlistをインクルードする際に

#define _SECURE_SCL 1 // 有効にする
//#define _SECURE_SCL 0 // 無効にする
#include <vector>

という感じで使います。
チェック付きイテレータとは何か、というのは
以下のMSDNを見て貰えるとよいと思います。
http://msdn.microsoft.com/ja-jp/library/aa985965.aspx


こちらを使っていて、起き得る問題についてのお話を今日は少し。

#include <cstdio>
#include <vector>

int main(int argc, char* argv[]) {
  typedef std::vector<int> IDs;
  printf("_SECURE_SCL = %d\n", _SECURE_SCL);
  printf("sizeof(IDs) = %d\n", sizeof(IDs));
  return 0;
}

こちらの、ただのstd::vectorのサイズを返すプログラムですが
_SECURE_SCLが、有効か無効かで異なる結果になります。


以下が、VisualStudio.net2010(VC10)での結果です。

_SECURE_SCL = 1
sizeof(IDs) = 20
_SECURE_SCL = 0
sizeof(IDs) = 16

と、_SECURE_SCLの設定で異なったサイズを返すのです。


これ単体では、確かにそう問題にはならないのですが、
例えば、スタティックライブラリと、それをリンクしている
メインプログラムで_SECURE_SCLの設定が異なった場合は
クラスサイズに齟齬が出る影響で、アクセス違反などを起こす場合があります。


また、これの厄介なところは、クラスサイズが異なるのは
「Release」のみです(正確には、NDEBUG定義の有無)。
_SECURE_SCL以外にも、定義の有無でサイズが変わるものは
同様の危険があるので、気をつける必要があると思います。