メイン | 2006年12月 »

前の10件 1  2  3  4

2006年11月 記事一覧

文字列を示す "abc"、_T("abc")、L"abc" は全て意味が違う!

文字を代入するときに使う " " (ダブルクオーテーション)。Windowsプログラミングでは_T(" ") を見かけることが多いから、それに倣って...

char	pszText[256];

strcpy(pszText,_T("あいうえお"));

というようなソースコードを書いていないだろうか?残念ながらこれは大きな間違えだ。実はこの _T(" ")いうのはcharやWCHARに対してTCHARがあるのと同じで、ユニコードビルド時はユニコード文字列を、非ユニコード文字列時はSHIFT-JISなどの文字列を指す文字列になる。
対してstrcpyが扱う文字列は常に非ユニコード文字列のみだ。つまりユニコードビルド時にchar型に対してWCHAR型のユニコード文字列を代入しようとするソースコードになっている。

char	pszText[256];

strcpy(pszText,"あいうえお");

だから上のように従来のようなソースコードが正しい。では文字列型にTCHARを利用した場合はどうだろうか?

TCHAR	pszText[256];

strcpy(pszText,"あいうえお");

上のソースコードも間違えだ。先ほど説明したようにstrcpyの引数は常にchar型なのに対し、このソースコードではユニコードビルド時にWCHAR型が渡されるからだ。ではどうしたらいいのかと言うと、

TCHAR	pszText[256];

_tcscpy(pszText,_T("あいうえお"));

上のようになる。strcpyの代わりに_tcscpyを利用して、さらに文字列は _T(" ") で囲む。
この_tcscpyというのはTCHAR型用の文字列コピー関数で、ユニコードビルド時はWCHAR型文字列のコピー用関数wcscpyを、非ユニコードビルド時は従来のstrcpyかマルチバイト文字列用の_mbscpyと同等の処理になる。

最後に残った L" " という文字列の表現は...ここまで読めば予想がつくだろう。そうこれはユニコード文字列を示すものだ。

WCHAR	pszText[256];

wcscpy(pszText,L"あいうえお");

上のように使われる。

文字列コピー用の関数としてstrcpyに対して_tcscpyやwcscpyがあるように、文字列を数字にするatoiにもTCHAR用の_tstoi、WCHAR用の_wtoiが用意されている。このほかの文字列を扱うクラスに対しても同様にTCHAR用とWCHAR用の関数がある。ユニコードビルドと非ユニコードビルドを切り替えれるプログラミングをしたい場合はこれらの違いに特に気をつけよう。

Vistaにも対応!Windows SDKをインストールする

WindowsSDKが知らないうちに公式リリースされていた。リリース日は2006年11月4日。名前は「Windows SDK」だが従来の「Platform SDK」と同じものだと思っていい。

ファイル名は「6.0.6000.0.0.WindowsSDK_Vista_rtm.DVD.Rel.img」でファイル容量は1187.5MB。
さっそくダウンロードし拡張子をisoに変更してインストールした。

■「Windows Software Development Kit for Windows Vista」というようになっている。これだけ見るとWindows Vista専用のSDK?とか思うかもしれない。しかし別段"専用"というわけではなく、単に.NET Framework 3.0などWindows Vistaに備わっている機能にも対応したという意味だ。
winsdk01.gif

■とりあえずライセンス画面。ありがちだけど読まずに次へ
winsdk02.gif

■インストールフォルダの設定。サンプルとその他のインストール先を別個に指定できる。私は変更しなかったが...かなり深いフォルダに入るので変更しておけばよかったと後悔。
winsdk03.gif

■ここでちょっとビックリ。デフォルトのインストール必要容量が2.3GB!そんなに空き容量ないんですけど...
winsdk04.gif

■ということでドキュメントや.NET Framework 3.0のサンプルなど私は使わないものをちょっとだけ削除。必要容量458MBまで削減した。
winsdk05.gif

■そしてインストール開始。
winsdk06.gif

■たった458MBのインストールだがかなり時間が必要だった。完全インストールしたら相当時間かかりそうな雰囲気。
winsdk07.gif

■お疲れ様でした。
winsdk08.gif

■...というわけにはいかない。次は「スタート」メニュー内できた「Windows SDK」メニューの「Visual Studio Registration」から「Integrate Windows SDK with Visual Studio 2005」を選択する。
winsdk12.gif

■そして警告画面を読んで「OK」ボタンをおす。この警告にはVisual Studio 2005のプロジェクトフォルダ関連のデフォルト設定が消えますよ、的なことが書かれている。
winsdk15.gif

■これでインストールが終了した。
winsdk14.gif


■もしもプロジェクトのフォルダに関する設定を変えていたなら...Visual Studio 2005で「ツール」メニューの「オプション」を選択して設定画面を開く。
winsdk09.gif

■そして左側のツリーにある「プロジェクトおよびソリューション」から「VC++ディレクトリ」を選択、ウインドウ右上で「インクルードファイル」や「ライブラリファイル」を選択して設定しなおそう。
winsdk13.gif


Visual Studio 2005のMSDNライブラリを新しくする

昔はMSDN Libraryというと年間1万円ぐらいだったか?で契約して送ってもらうことになっていた。「お金を払ってまでたかだかヘルプは欲しくない!」ということでMSDN Universalを契約して各種OSなどを送ってもらっていたものだが...
うれしいことに今ではCD版のMSDNも無料化されている。特別にダウンロードできるようになっているのか、それともこれからずっと無料で定期的に提供され続けるのかは不明だ。しかし少なくとも2006年6月版と2006年8月版のMSDN Libraryは無料でダウンロードできる。
ちなみに公開されたのは2006年6月版が6月、2006年8月版は11月だ。今後はどのくらいの頻度で更新されるのだろうか...


MSDN ライブラリ 2006年8月版

MSDN ライブラリ 2006年6月版

ダウンロードできるのは日本語と英語版のMSDNライブラリのCDイメージだ。もちろんVisual Studio 2005にも対応している。


msdn01.gif

msdn02.gif

msdn03.gif

msdn04.gif

msdn05.gif

msdn06.gif

msdn07.gif

msdn08.gif

msdn09.gif

msdn10.gif

strcpyや_tcscpy、wcscpyなどは使うな!

ちょっと過激なタイトルだが...Visual Studio 2005でstrcpyを使うと以下のような警告が出る。

void	Test(void)
{
	char	pszText[256];

strcpy(pszText,"あいうえお");
}


test26_01.gif

「warning C4996: 'strcpy' が古い形式として宣言されました。'strcpy' の宣言を確認してください。」というのはあくまでも警告であってエラーではない。そのため...

#define _CRT_SECURE_NO_DEPRECATE

#define WIN32_LEAN_AND_MEAN // Windows ヘッダーから使用されていない部分を除外します。
// Windows ヘッダー ファイル:
#include <windows.h>

// C ランタイム ヘッダー ファイル
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>

void Test(void)
{
char pszText[256];

strcpy(pszText,"あいうえお");
}

というように「_CRT_SECURE_NO_DEPRECATE」の定義を一番初めにおこなっておけば、この警告は出ないし、プログラムもきちんと動く。しかし、だからと言ってこれは警告を無視しているだけであって根本的な問題は何も変わっていない。


strcpyを使うと何が問題なのかと言うと、コピー先のバッファー容量が指定されていない点だ。つまり、

void	Test(void)
{
	//1バイトしか確保していない!
	char	pszText[1];

//8バイトも代入してる!
strcpy(pszText,"abcdefg");
}

こんなソースコードを動かしたときにいわゆるバッファーオーバーランという状態になる。

デバッグ環境であれば
test26_02.gif
こんなエラー画面が表示されてプログラムが途中で止まるし、リリースコードでは悪意を持った者の攻撃対象となりうる。

正直なところを言うと、普通のフリーソフトを作っている開発者や趣味でプログラミングをしている人、仕事であってもカスタムソフト的なこじんまりしたソフトを作っている場合にはそこまで考えてプログラムする必要はないと思う。
しかし最近は小さいソフト会社でも「セキュリティが高いソフト」を開発しているとうたっている。内容をよくよく聞いてみると「保存データを暗号化してるからセキュリティが高い」とか「SSLで通信してるからセキュリティが高い」というような感じで、ソフト全体の開発にセキュリティを意識しているというわけではなく、ほんの一部分だけセキュリティを意識しただけで実は全然セキュリティが高くないソフトを販売していたりする。今後セキュリティが少しでも高いソフトウエアを開発したいと思っている場合は、まずは手始めにstrcpyの使用で出るような警告部分を修正するといいだろう(ちなみに私はセキュリティが本当に高いソフトを開発するだけの能力は持ち合わせていないのでこんなことを書いていいものかとも思うのだが...)。

ではどのようにすれば警告が出なくなり(少しは)安全なソースコードになるかと言うと

void	Test(void)
{
	char	pszText[256];

strcpy_s(pszText,256,"あいうえお");
}

このようにstrcpyの代わりにstrcpy_sという関数を利用する。この関数では第二引数にpszTextで確保されている大きさを渡すようにできている。これにより、strcpy_s内部では文字列をコピーする前にコピー先に十分な領域があるかをチェックすることができ、バッファーオーバーランを未然に防ぐことができる。


とは言うものの以下のようにするとやはり文字列のコピーに確保された容量が足りないため、エラーになることはなる。しかしデバッグビルドではアサーションエラー、リリースビルドでは単に強制終了になるなどバッファーオーバーランよりはましだ。

void	Test(void)
{
char pszText[1];

strcpy_s(pszText,1,"あいうえお");
}


test26_03.gif


strcpyに対してstrcpy_sが作られたように、wcscpyにはwcscpy_s、_tcscpyには_tcscpy_sが用意されている。また、同じようにstrncpyにもstrncpy_s、_tcsncpyに_tcsncpy_s...従来の関数名に「_s」を付加したものがある。警告が出たときは無視せずに置き換えるようにしよう。

前の10件 1  2  3  4





usefullcode@gmail.com

About 2006年11月

2006年11月にブログ「UsefullCode.net」に投稿されたすべてのエントリーです。

次の記事は2006年12月です。

他にも多くのエントリーがあります。メインページ記事一覧も見てください。