WindowsプログラマのWebアプリへの挑戦日記。あとパンとか。

Archive for the ‘プログラミング’ Category

スレッドを_endthreadで終わったらメモリリーク

火曜日, 3月 18th, 2008 Posted in C++ | 3 Comments »

c++のスレッドの話。

今回はまったのは、_beginthreadで開始したスレッドを終了するとメモリリークが発生していた件。

ざっと見た感じ解放忘れとかなさそうな感じだったので原因の発見に時間がかかった。

スレッドの最後で_endthreadをコールしていたんだけど、これをコメントアウトするとメモリリークが消えた。

なんで?と思って調べてみると、簡単なことだった。

例えば次のような関数を_beginthreadで呼んだとする。

  1. void ThreadFunction( void* )
  2. {
  3. CString strFilePath = "G:\\test.mp3";
  4.  
  5. //MP3を再生する関数
  6. PlayMp3( strFilePath );
  7.  
  8. _endthread();
  9. }

あ、VCです。

strFilePathのスコープは関数内で、この関数を抜けるときにデストラクタが呼ばれる。

つまり、関数の最後の”}”まで行けばstrFilePathのデストラクタが呼ばれて幸せなんだけど、_endthread()で強引にスレッドを抜けてしまうと、デストラクタが呼ばれずにメモリリークしてしまう。

こんな簡単なコードだとわかりやすいんだけど、これが実際のコードとなるとぜんぜん気づかない・・・。

以後気をつけます。

cakePHPでJavascriptを出力する

日曜日, 2月 3rd, 2008 Posted in cakePHP, PHP | 2 Comments »

HTMLに以下のようなJavascriptのコードを埋め込み、srcでPHPなどの動的な処理をするファイルを指定すると、静的なHTMLに動的な処理を埋め込むことが出来ます。アクセス解析のサービスなどでよくありますね。

  1. <script src="xxx.php" type="text/javascript"></script>

で、srcにPHPのファイルを指定し、PHP側でJavascriptのコードを出力する処理を書けば実現できます。詳しいやり方は、PHP:JS(JavaScript)からPHPを呼び出しHTML上に出力する方法に丁寧に書かれているので参考にしてください。

で、cakePHPでこの処理を書こうと思ったわけです。まずは、Javacsriptを呼び出すHTML側では、

  1. <script src="/app/[コントローラー]/[メソッド]/[プロパティ]" type="text/javascript" charset="utf-8"></script>

のように書きます。controller側のメソッドでは、最初に

  1. header("Content-type: application/x-javascript");

を書く必要があるようです。viewでheaderを出力すると、Javascriptとして認識されません。

cakePHPの/app/core.phpのDEBUGモードが0以外だと余計なモノが出力されるのでJavascriptとして認識されないみたいです。ボクは動作確認はDEBUGモードを0にしてやっています。特定の場合だけDEBUG出力を抑制することは出来ないモノですかね。

BYTEの配列データをVARIANTのSAFEARRAY(VT_ARRAY)に変換する

木曜日, 1月 31st, 2008 Posted in C++ | 1 Comment »

今回は、C++に関するエントリー。本業はC++なので、こういうのもありかなと。

VARIANTにデータを設定するのはいつもついつい調べ直してしまいます。今回は、BYTE型のデータをSAFEARRAY型に流し込む方法。調べ直していたところ、ORiN協議会◇技術解説の説明がとてもわかりやすかったので、うれしさついでに関数化してみました。

  1. BOOL ByteArrayToVariant(BYTE* pBytes, int size, VARIANT& v)
  2. {
  3.     SAFEARRAYBOUND rgb[1];
  4.     rgb[0].cElements = size;
  5.     rgb[0].lLbound = 0;
  6.  
  7.     SAFEARRAY* psa = SafeArrayCreate(VT_UI1,1, rgb);
  8.     if(!psa)
  9.         return FALSE;
  10.  
  11.     void HUGEP *pvData;
  12.     HRESULT hr = SafeArrayAccessData(psa, &pvData);
  13.     if(S_OK!=hr)
  14.         return FALSE;
  15.  
  16.     memcpy( pvData, pBytes, size );
  17.  
  18.     hr = SafeArrayUnaccessData(psa);
  19.     if(S_OK!=hr)
  20.         return FALSE;
  21.  
  22.     v.parray = psa;
  23.     v.vt = VT_ARRAY | VT_UI1;
  24.  
  25.     return TRUE;
  26. }

関数の説明

  1. SAFEARRAYBOUND rgb[1];

SAFEARRAYBOUNDは、SAFEARRAYの要素数とインデックスの下限値を設定する。BOUNDには「限度,範囲」なんて意味があるので、わかりやすいネーミングですね。次に、

  1. SAFEARRAY* psa = SafeArrayCreate(VT_UI1,1, rgb);

で、SAFEARRAYの実体を作ります。今回は、BYTEの配列なのでVT_UI1を指定します。SAFEARRAYのデータへは、SafeArrayAccessData()をコールすることでアクセスできるようになります。

  1. void HUGEP *pvData;
  2. HRESULT hr = SafeArrayAccessData(psa, &pvData);

コピー元のデータをSafeArrayAccessData()で取得した配列へコピーします。

  1. memcpy( pvData, pBytes, size );

SafeArrayAccessData()したら必ず、SafeArrayUnaccessData()をコールします。

  1. hr = SafeArrayUnaccessData(psa);

最後にVARIANT型の引数にデータを設定しておしまいです。

  1. v.parray = psa;
  2. v.vt = VT_ARRAY | VT_UI1;

ByteArrayToVariant()の呼び元でVARIANTを使った後に、

  1. HRESULT SafeArrayDestroy( v.parray );

をコールするとなんか不適切なメモリを解放してしまうようで、なんとなく不安定になりました。なんででしょうねぇ。

Amazon Webサービスを利用するサイトをcakePHPで構築

月曜日, 1月 14th, 2008 Posted in cakePHP, PHP | 5 Comments »

せっかくのMVCなので、Amazon Webサービスからデータを取得する処理をModelとして実装してみました。

ModelではとりあえずfindAllのみをオーバーライドします。後で必要になれば必要な関数をオーバーライドするつもりです。Modelは以下の通り。

  1. class Aws extends AppModel {
  2.  
  3.     var $name = 'Aws';
  4.    
  5.     var $useTable = false;
  6.    
  7.     function findAll( $category, $keyword, $count ){
  8.         //データの取得処理を実装
  9.     }
  10. }

実際にAmazon Webサービスからデータを取得する処理は、「ITmedia エンタープライズ:特集:後編 WebサービスをAmazonで知る――PHPでECS 4.0を使うテクニック (1/5)」を参考にしました。

ModelでDBテーブルを使わない場合は、

  1. var $useTable = false;

と書くとDBテーブルにアクセスしないらしい。

controllerでは、対応するDB以外のModelを使う場合、

  1. class BillsController extends AppController {
  2.  
  3.     var $name = 'Bills';
  4.     var $helpers = array('Html', 'Form' );
  5.     var $uses = array( 'Bill', 'Aws' );
  6.    
  7.     //以下略
  8. }

のように使うModelを配列で宣言する。このとき対応するcontrollerに対応したDBも配列に入れることを忘れずに。

coreserverでcakePHPを試す

月曜日, 1月 14th, 2008 Posted in cakePHP, PHP | 1 Comment »

cakePHPの動作環境をレンタルサーバーのcoreserver上に構築します。ローカルでの動作確認はCakePHPをローカルで試すを参照してください。

cakePHPはダウンロードしてきたモジュールを解凍すると、次のようなフォルダ構成になります。

  1. /cakeroot
  2.     /app
  3.         /config
  4.         /controllers
  5.         /models
  6.         /plugins
  7.         /tmp
  8.         /vendors
  9.         /views
  10.         /webroot
  11.         .htaccess
  12.         index.php
  13.     /cake
  14.     /vendors
  15.     .htaccess
  16.     index.php

レンタルサーバーで複数のcakePHPアプリを動作させる場合、容量を節約したいなどの理由でcakePHPのcoreは共通のファイルを参照したいと思って、次のような構成に変更しました。

  1. /virtual/xxx/lib/cake_core
  2.     /cake
  3.     /vendors
  4.    
  5. /virtual/xxx/public_html/caketest.xxx.com/
  6.     /app
  7.         /config
  8.         /controllers
  9.         /models
  10.         /plugins
  11.         /tmp
  12.         /vendors
  13.         /views
  14.         /webroot
  15.         .htaccess
  16.         index.php
  17.     .htaccess
  18.     index.php

/virtual/xxx/lib/cake_coreは複数のcakePHPアプリで共通とし、アプリごとに/virtual/xxx/public_html/caketest.xxx.com/以下のようにフォルダを構成します。

フォルダ構成を変更したことで次のファイルを編集します。/virtual/xxx/public_html/caketest.xxx.com/app/webroot/index.phpの、

  1. define('CAKE_CORE_INCLUDE_PATH', ROOT);

  1. define( 'CAKE_CORE_INCLUDE_PATH', DS.'virtual'.DS.'xxx'.DS.'lib'.DS.'cake_core' );

に変更します。

/virtual/xxx/public_html/caketest.xxx.com/index.phpの

  1. define('CAKE_CORE_INCLUDE_PATH', ROOT);

  1. define( 'CAKE_CORE_INCLUDE_PATH', DS.'virtual'.DS.'xxx'.DS.'lib'.DS.'cake_core' );

に変更します。

これでhttp://caketest.xxx.com/postsにアクセスしちゃんとなにやらエラーがでます。どうやらアクセス権のエラーっぽいので、/virtual/xxx/public_html/caketest.xxx.com/app/tmp/cache/modelsの、default_xxx_caketest_listとdefault_postsの属性を757に変更するとちゃんと表示されました。どうやら、/virtual/xxx/public_html/caketest.xxx.com/app/tmp/cache以下のディレクトリの属性を変更した方が良さそうです。

追記:2008/05/12

なんだかファイルの編集する箇所が大幅に間違っていたので訂正しました。

CakePHPをローカルで試す

火曜日, 1月 8th, 2008 Posted in cakePHP, PHP | No Comments »

PHPのフレームワーク、CakePHPをローカルで試してみました。基本はCakePHP プログラマーズ リファレンスガイドの通りにやればいいんですが、ちょっと気になることなどをメモします。

ローカルの環境はWindows Vistaにxamppを入れています。

  1. CakePHPのインストール

    CakePHPからcake_1.1.18.5850.zipをダウンロード。1.2系はまだbetaっぽいので1.1系で。C:\xampp\htdocsに解凍。

  2. DBの作成

    A.3.ブログデータベースの作成の通りにテーブルとデータを作成。
    /app/config/database.php.defaultを/app/config/database.phpにリネームする。/app/config/database.phpの$defaultを作成したDBに併せて変更

    1. <br />
    2. var $default = array('driver' => 'mysql',<br />
    3. 'connect' => 'mysql_connect',<br />
    4. 'host' => 'localhost',<br />
    5. 'login' => 'ユーザ名',<br />
    6. 'password' => 'DBパスワード',<br />
    7. 'database' => 'DB名',<br />
    8. 'prefix' => '');<br />

    ここまででいったんhttp://localhost/cakeにアクセスしてみると、

    Your database configuration file is present.
    Cake is able to connect to the database.

    と表示され問題ないことを確認する。

  3. Modelの作成

    A.6.Post Model の作成の通りに/app/models/post.phpを作成する。

  4. Controllerの作成

    A.7.Posts Controller の作成の通りに/app/controllers/posts_controller.phpを作成する。controllerからは$this->PostでModelにアクセスできる。

  5. Viewの作成

    ビューのファイルは、/app/views以下に対応するコントローラにあうフォルダを作成する必要がある。今回はpostsというフォルダを作成する。A.8.Posts Controller の作成の通りに/app/views/posts/index.thtmlを作成する。

    とりあえずここでhttp://localhost/cake/posts/indexにアクセスしてみる。んが、文字化け。UTF-8で保存したら文字化けするみたい。Shift-JISで保存すると問題ない。どこかに文字コードの設定があると思うんだけど、また今度調べよう。

    続いて/app/controllers/posts_controller.phpにfunction view()を追加。これで投稿された記事を個別に見れるようになる。

    さらにA.9.Posts の追加の通りに/app/controllers/posts_controller.phpにfunction add()を追加。フォームデータをPOSTで送信したら、$this->params[form]でフォームに入力されたデータにアクセスできるらしい。htmlヘルパーの$html->inputなどを使ってフォームの内容を送信すると$this->data['モデル']['フィールド名']でアクセスできる。

    A.10.データバリデーションの通りに/app/views/posts/add.thtmlを作成し、新規作成画面のviewを作成する。

    HtmlHelperの$html->input、$html->textareaの第一引数は対応するモデル/フィールドを指定する。第二引数はフォームの属性などを指定。’size’=>’40′で入力フィールドのサイズに40を指定。

    モデル(/app/models/post.php)に$validateを定義することによってsaveが呼ばれたときにフォームからの入力をチェック(validate)することができる。新規作成画面へのリンクを表示するために/app/views/posts/index.thtmlに/posts/addへのリンクを作成。

    1. < ?php echo $html->link( "新規投稿", "/posts/add" ); ?></p>
    2. <p>

ローカルでは特に問題なく動作しているので、次回はcoreserverで試してみます。

開発メモ

木曜日, 1月 3rd, 2008 Posted in サーバー | No Comments »

このブログは、Webプログラミング素人の管理人が調べたことややったことのメモを書いていきます。

最近初めてレンタルサーバーと契約してみました。Webサーバー管理についても素人です。レンタルサーバーはcoreserverです。Webアプリを開発するにあたってのいろんな環境設定はcoreserverだけで確認します。