2006.01.20

コーディングしたい!

諸事情により、全然コーディング作業ができてません。プライベートも仕事でも。

あー、コーディングしたい!やりたいことは既にあるんですが、時間がない…。時間を作るには、週末の家族サービスを放棄するしかなさそうです。

| | TrackBack (0)

2005.09.22

物を作るって?

プログラムを始めた頃は、物ができること自体が楽しくて仕方ありませんでした。

そこから成長すると、次はできる物自体の品質を上げていくことが楽しくて仕方なくなります。

で、最終的には作り方を色々と考えていったりします。おそらく、ほぼ全てのプログラマがこういう段階を踏んでいくでしょう。

その道程は経験してきたことだし、これから経験する人も沢山いると思います。

でも、忘れちゃいけないのはプログラミングって作業は、「目的」があってやるもんです。言い換えると、目的が達成できさえすれば「作り方」なんてのはどうでもいいんです。

こういう話って色んなところで繰り返しなされてると思いますが、今現在の私の素直な気持ちとしてチラシの裏代わりに書いておきます。

| | TrackBack (0)

2005.06.28

UML初心者への言葉

UMLという言葉を初めて聞いたときから、もう何年が経ったでしょうか。

私が生まれて初めて聞いたモデリング手法は、「OMT」というUMLが統合したモデリング技術の一つでした。これを入社したてのぺーぺーの頃に「車のエンジン部をクラス図で書きなさい」などといわれて、車の構造すら分からないのに四苦八苦しながら書きつづけ何度も訂正させられて、「二度と使うかばかやろー」と思ったのを覚えています。

このクラス図を実際の実務で使ってみて「お、便利じゃん」って思ったのは、つい先週ぐらいの事なんですが。それまでは、上司に言われるから書くだけで書き捨て状態でした。

さて、このUMLに関してですが実務を経験した中からUMLにはいくつものモデリング手法があるのですが、私はこの中のシーケンス図とクラス図しか実務では使ったことありませんでした。(クラス図は最初の入り口が、OMTというあまりに難しい手法過ぎたので未だに苦手です。)

クラス図と違ってシーケンス図は凄くアバウトに書けて、処理内容を図を見た全員が説明も要らないほど簡単に理解できる図としては最強だと思います。そういう理由から、私は外注との仕様確定時にシーケンス図を使うことを常としていました。下手すると、最初の打ち合わせ時にはシーケンス図しか持っていかないなんてことも。まあ、これは単なる手抜きなんでシーケンス図では表現できない契約上必要な仕様はきちんと書いていかないといけません(^^;。

もし、UMLアレルギーを既に発症してる方が居たとしたら、大抵のUML入門の入り口に位置しているクラス図を一度捨ててください。そして、自分でも「ココの処理内容は何かに書き残しておきたいな」と思った処理をシーケンス図に落とし込んでみてください。

凄く楽に書けて、凄く説得力のある図が書けます。ぜひお試しを。

と、偉そうに書いてみましたが、実はUMLはほぼ独学です。シーケンス図も、Visioを使いながら覚えたようなもんです。よって「正しいシーケンス図」を学んだことは一度もありません。

でも、UMLはコミュニケーションのためのツールに過ぎません。乱暴に言い換えると、日本語や英語などの言葉と同じようなもんです。一番大事なことは、伝えたいことが相手に伝わることであり、ツールの使い方が仕様どおりで正しいことってのは、その次ぐらいに大事なことになるでしょう。つまり、正しくても伝えたい相手に正確に伝わらないなら駄目な図であり、正しくなくても伝えたい相手に正確に伝わるなら、正しくない方が良いのです。

よって、私は相関を表現する線や矢印記号に込められる正しい仕様上の意味に、それほど期待はしていません。UMLの入り口に立った方は、最初は単なる実線のみの図を作成すると良いでしょう。そして、実線だけでは表現しきれないと感じてから、実線以外の線の意味を知れば良いと思います。但し、伝えたい相手が同じように成長してくれないと意味がないわけですが^^;。

| | TrackBack (0)

2004.12.27

XMLHTTPコンポーネントの謎

MSXMLにはXMLHTTPという、非常に使い勝手の良いHTTP通信用のコンポーネントが内蔵されている。これが一番良い点は、IEでの通信と同じ通信をしてくれるという点だ。HTTP通信を別コンポーネントでやると、IEで繋がるのに、なんでこのソフトでは繋がらないんだというのを、いちいち言い訳しなくてはならなくなる。

そういう言い訳をしなくても良いというだけでも素晴らしいのに、使い勝手も申し分ない。それまで、ユーザーに散々言い訳を並べてきたサポート部隊である私としては、このコンポーネントの存在を知ったときは、小躍りしてしまった。いいぞいいぞ。

しかし、つい先日判明した事実なのだが、どうもPOSTででかいサイズのファイルを受信しようとすると、5MBを超えたあたりから異常に遅くなるという事実が判明した。これが、GETなら特に問題はないようだ。(GETとPOSTで全く同じURLを開いて同じ結果が得られる環境を用意してるわけではないので、本当にPOSTだから不味いのかは分からない。)

つまりは、発注元から「5MB超えたら遅くなるので修正してくれ」と来たのである。修正方法を探してるのだが、日本語ではまともにXMLHTTPを解説してくれてるありがたいサイトはないので、英語のページを漁ってたりする。これが、修正方法が見つからない。これは、もしかしてHTTP通信部分を別コンポーネントでやるしかないのか。

というか、誰か良いサイトか良い情報持ってたら、こっそり教えてください。

| | TrackBack (0)

2004.12.24

NMFTPの馬鹿!

仕事でBorland C++ Builder5を使ってます。Web系の開発も、極々偶にやるんですが、その際自力でRFCを読んで開発するわけもなく、インターネットコンポーネントを最大限に活用します。

BCB5にはNM系のコンポーネントが標準装備されているので、もう4年ぐらい前にですが、NMHTTPとNMFTPを利用したActiveXのソフトウェアを作成しました。正確には、私が作らせたわけでも私が作ったわけでもなくて、上司が外注に作らせて、出来上がってきたソースを、「再構築して、メンテナンスおねがいね」とポンっと渡されただけなんですが。

NM系コンポーネントは、当時から既に悪名が高くて有名でした。外注に発注する前の上司からの相談で、私はNM系を使うのは反対したのですが、私の意見は反映されなかったようです。

まあ、それほど複雑なことをしてるわけでもないし、何よりユーザー数が圧倒的に少ないのが良かったのか、特に大きな問題も今までは発生することはありませんでした。

そして、何年も経った今になって問題が発生します。その発端はWindowsXPのSP2です。XP SP2のファイアーウォール機能を使用すると、NMFTPの「切断時」に例外が発生します。調べると、コンポーネントの切断メソッドの内部で例外が発生しているようです。

原因を調べていくと、どうやらFTPは二つのポートを使うのですが、この二つのポートを閉じる順番に問題があることが分かってきました。このあたりの詳しい説明は、「インターネット・プロトコル詳説(10) FTP(File Transfer Protocol)」でも読んでください。

んで、NMFTPの通信のログを確認すると、間違いなく閉じる順番を間違ってるんですよね。つまりは単純なミスだってことです。今まで発覚しなかったのは、単に「偶々動いてたから」という理由だけです。なんてこったいorz。

この不具合の対処は、ソースを購入して修正するか、別のコンポーネントを利用するか、自作するかの3つの対処方法があります。作業する時間もないし、ユーザーが急いでるということだったので、この3つのまともな修正方法ではなく、お手軽な修正を行いました。それは、とりあえずまともに動作してるように見せかけるために、例外をキャッチしてスルーするという手法です。

この「とりあえず」が、永遠にそのままな気がしてなりません。作業する時間がそれなりに必要だからなぁ…。

| | TrackBack (1)

2004.10.30

BCBコンポとツール

私が使用してる、BCBのコンポとツールをフリーのもの限定で記録しておく。あくまで、自分用。

RxLib
http://rxlib.wz.cz/

GExpert
http://www.gexperts.org/

上記二つだけだけど、これで完璧。

| | Comments (0) | TrackBack (0)

2004.09.18

飽きれ果てた話

無限ツリー階層をDBのテーブル形式で保持する手法で一般的なのは、親は子知らず型という奴です。

簡単に親は子知らず型を説明すると、テーブルの項目に「親ID」なる項目を設け、子供だけが親のIDを知っておくという形にしておきます。そうすれば、簡単に無限ツリー階層を構築することができます。ルート階層は、親IDがNULLのレコードに当たるわけですね。

まあ、極一般的な手法だとは思いますが、私が飽きれたのは、お役所が作ったある仕様改訂の話。

改訂なので、以前の仕様があるわけですが、以前の仕様になかった親子関係をあるオブジェクト間に構築しようとしたようです。そこで親子関係を作るために、「上位ID」と「下位ID」なる属性が追加されました。そして、この属性の記述方法は、XMLのAttributeで記述するとのこと。ちなみに、XMLタグ内のAttributeは同じAttributeを複数個書けません。

ココまで書けば、想像できると思いますが、この仕様だと大きな制限として、親は子供を一個しか持てないという制限ができるんですよね。

んで、仕様上も実運用上も親は子供を一個しか持てない制限があって構わないというなら話は分かるんです。

でも、どう見ても実運用上で複数の子供を持てるようにしないと不味そう。そう思って、現在仕様作成元に問合せを行なってたりします。親も子も相手を知ってる形にする意味とか考えたんでしょうかね?それとも、完全な素人が全国で利用する仕様書を作成してるのでしょうか?だとしたら、仕事を舐めすぎだと思いますが。

#もし、これが外注に作らせてるとか、どっか詳しい会社に内容をチェックしてもらってるとかだったら、単なる税金の無駄遣いですね。

| | Comments (0) | TrackBack (0)

2004.08.20

WindowsXP SP2の変更点

WindowsXPのSP2が出るということで、うちのソフトが動くのかをチェックしてみました。

チェックする前に、何が変更になったかを下調べです。

Windows XP Service Pack 2: 開発者向け情報

調べてみると、関係がありそうなのはRPCの匿名アクセスが制限されるという項目だけです。んで、実際にSP2(RC2)環境にてチェックしてみると、やっぱりRPCができないようです。

そりゃ、通信時に何かセキュリティかけてるわけじゃないので、繋がらないのも無理はありません。そういう仕様変更なんですからね。

んで、修正方法を調べてみると、修正方法は3つあって、「A.匿名アクセス禁止にする」か、「B.匿名アクセス許可にする」か、「C.システム設定を弄って全部匿名OKにする」かの3つのパターンがあります。

Cの対応なんてもっての他なので、AかBの対応になります。Aの修正をするとなると、サーバー側とクライアント側の両方を弄らないといけません。というわけで、まずはBの対応をしてチェックしてみました。

すると、問題なく動作しました。対応方法は間違ってなかったようです。後は匿名禁止にするために、Aの対応をするだけです。

で、ここであまりにあっさり対応できたことで、大半の技術者は本来WindowsXP SP2が求めたセキュリティレベルである「A」の対応をせずに、「B」の対応をしてしまうんじゃないかという考えが浮かんできます。それほど、開発者の中に「セキュリティ」に対する意識は高くないということです。

実は、この問題は開発者以上に、現場の方がセキュリティに対する意識が低いことに起因します。つまり、開発者というのは、エンドユーザーが求める物を作るだけで、啓蒙する立場にないと考える人が多いのです。啓蒙しても、直接的にお金にはなりませんからね。

そして、問合せ等で聞かれて対処するときに良く言われる言葉は「動けばいいから」という言葉があります。今回のせっかくのセキュリティ強化も「動けばいい」的発想で、上記のBの対応がなされるとしたら悲しい限りです。

もっと言うなら、Cの対応する人って多いだろうなぁ。だって、コーディング一切ありませんもん。設定変更するための手順書作っておしまいですからね。

| | Comments (0) | TrackBack (0)

2004.08.11

InstallShield 1607 エラーに悩まされる

勤務先で作ってるソフトウェアの配布で、インストーラはInstallShieldを利用して作っている。

しかし、このInstallShieldは様々なユーザ環境に耐えうるだけの品質を持っていないことが判明しつつある。

一番嫌なエラーが「1607」というエラーで、正直原因などこれっぽっちも分からないエラーである。私の勤務先の会社だけじゃなくて、様々な会社が、この1607エラーには悩まされているようで、googleで「InstallShield 1607」で検索すると対処法が沢山見つかる。

んで、この対処法の一つとして「isscript.msi」を実行するというのがあるんだが、このインストーラを実行すると、1327というエラーコードが出ることがあり、上の1607になる原因のほとんどは、ほとんどがisscript.msiの1327に起因するようである。

1327が発生するケースで一番可能性があるケースは、「CD-ROMのドライブ文字を変更している」ケースだ。ほとんどのユーザが、たったこれだけの事で困ってしまうという状況・・・。

というか、ドライブ文字変更したらインストールできないって、全然理解できん。どんな制限だっちゅーの(^^;。


ちなみに、1607エラーは月に数回電話がかかってくる。たかだか数百本のユーザーなのに!こんなんで良いんの?InstallShieldさん。

| | Comments (0) | TrackBack (0)

2004.08.03

仕事でのミス

更新がストップしてる間、仕事のミスを連発させてました。しかも、かなりヤバゲな奴。

まあ、多数のエンドユーザに影響あるんじゃなくて、極少数の協力会社に対してのみ迷惑かける形のミスなんですが、会社として品質管理の問題を問われかねないぐらいヤバイ奴だったりします。

なんせ、一度でもコマンド実行したら100%発生する不具合ですから(汗)。

まあ、その他の条件が無いわけじゃないですけどね。見事に、その他の条件に当てはまる環境でしかチェックしてなかったというお粗末な不具合でした。

久しぶりの投稿が、こんな懺悔っぽい形の投稿ですみません・・・。

| | Comments (0) | TrackBack (0)

2004.07.14

こ、このソースは・・・

外注先に作らせたプログラムのソースを修正中、とんでもないソースにぶちあたったので、思わず作り替えしてしまいました。

頼むから、1関数が1000行を超えてるソースを、こんなに連発させないでください。メンテナンス性も全く考慮されてません。

とか、ぶつぶつやってたら、外注に任せる予定の作業までやってしまいました(屍)。外注に出す仕事を他に無理やりでも捻出しなきゃ・・・。(外注先の確保のため)

なんか、凄く無駄な感じ。

| | Comments (0) | TrackBack (0)

2004.07.09

デスマーチ

デスマーチ

自分で工数を見積もって仕事をスケジューリングするようになってからは発生してませんが、会社入りたての頃は無茶な開発要求があって、実際にデスマーチっぽい案件もあったりしました。(二ヶ月で休日1日とか、もちろん毎日家に帰るのは日付変わった後)

そして、プログラマが徹夜当たり前なんて風潮があったのも現実です。「そんな馬鹿な!」と内心思ってましたが、先輩や上司が本当に徹夜しまくってるんですよ。怖い世界でした。

もう、最近はそういうこともありません。だって私は、3年ほど徹夜してません。残業もほとんどしません。

で、偶に外に出てお客さんと話をすると「毎日何時ぐらいまで仕事されてますか?やっぱり忙しいですか?」なんて聞かれたりするとちょっと困ります。だって、これ聞いてくる人って「徹夜自慢」するタイプの人ばっかりですから。

| | Comments (0) | TrackBack (0)

2004.07.06

今日の仕事はだるい仕事

なんでリレーションしてないのかなぁ。違う値に対するリストを全部別テーブルにしてるせいで、テーブル数が1000個超えてるよ!今回の追加分をその方式に合わせて追加すると、更に1000個のテーブルを追加することになる。

んなアホな!

というわけで、仕様変更から始めなきゃ・・・。ぐったり。

| | Comments (0) | TrackBack (0)

2004.07.02

ぶらんこの諷刺画

117教祖のお話

プログラム組んでる人も、仕事とってくる営業の人も、設計してる設計者も、プロジェクト管理してるマネージャーも皆一度は読むべし

損はしません、させません。ぜひ。

あ、有名なんで知ってました?だとしたらごめんなさい。

| | Comments (0) | TrackBack (0)

2004.06.29

米Sun、VBライクなJava開発ツール「Java Studio Creator」を正式発表

米Sun、VBライクなJava開発ツール「Java Studio Creator」を正式発表

JBuilderしか使ったことないけど、これも一度試してみよう。楽しみ楽しみ。

| | Comments (0) | TrackBack (0)

2004.06.16

エクスプローラの縮小画像表示2

先日書いた、この件について、ようやく取得できるようになりました。

SH系は使ったことあったんですが、IExtractImageオブジェクトを取得するためのIShellFolder::GetUIObjectOfというメソッドを使ったことなかったので、かなり苦労しました。

IShellFolder自体はSHGetDesktopFolderというAPIでゲットできるんで、最初、ココで手に入れたIShellFolderオブジェクトに対してGetUIObjectOfメソッドを使用してたんですが、これだと上手くいきませんでした。問題は、GetUIObjectOfがターゲットとするItemIDListというのがあるんですが、これにちゃんと対応できてるIShellFolderオブジェクトじゃないとダメだったんです。

BCB専用のクラスにしてしまいましたんで、全てのコードをアップすることは難しいですが、簡単な流れを書いておきます。

1.SHGetDesktopFolderを使って、ルートのIShellFolderを取得
2.1のIShellFolder::ParseDisplayNameを利用して、目的ファイルのあるフォルダのITEMIDLISTを取得
3.2で手に入れたITEMIDLISTから、IShellFolder::BindToObjectを利用してIShellFolderオブジェクト取得
4.3のIShellFolder::ParseDisplayNameを利用して、目的ファイルのITEMIDLISTを取得
5.3のIShellFolder::GetUIObjectOfを利用して、IExtractImageオブジェクトを取得
6.5で手に入れたIExtractImage::GetLocationをコールして、作成する縮小画像の設定を行う
7.5で手に入れたIExtractImage::ExtractでHBITMAPをゲット
8.後は適宜後始末

ITEMIDLISTの後始末にIMallocを利用するのは言うまでもありません。

と、全部書いて分かったのですが、上記じゃチンプンカンプンですね(汁)。とりあえず、私が作ったクラスでも公開しておきます。間違いなどあったら指摘してくれるとありがたいです。

UHppExtractImage.LZH(BCB5で作成)

| | Comments (0) | TrackBack (0)

2004.06.14

エクスプローラの縮小画像表示

まだ調査段階なんだけど、エクスプローラの縮小画像表示機能を利用して、ファイルのサムネイルを表示する機能を作る必要が出てきました。

んで、軽く調べたところ、IExtractImageというインターフェースを利用すれば良いとのこと。これ、私が使ってる統合環境のBCB5には定義がないんで、別のところからヘッダーファイルを借用して利用することになりそうです。とほほ。

こういうときに、統合環境が古い点が悩ましくなります。それ以外は全く問題ないんですけどね。

上記エクスプローラの縮小画像を取るコードができたら、詳細をアップしようと思います。

| | Comments (1) | TrackBack (0)

2004.06.04

DOMオブジェクト

大昔から使ってるソースに根本的な問題があるっぽくて、今DOMオブジェクトの操作部分の修正をしています。

最初チンプンカンプンだったんですが、なんとか分かりかけてきた頃に、不具合も修正しきってしまいました。

なんか、中途半端に理解してしまったので、ちょっと消化不良気味だったりします。

家に帰ってから、一度真剣にあれこれ触ってみようかな。しかも、日本語で全てを網羅してるページってないんですね。・・・うーん、ネットゲームを中断してる間に専用サイトを作ってみようかなぁ。

| | Comments (0) | TrackBack (0)

2004.05.21

エクスプローラと同じ判定

コードを書こうと思ったけど、ココログってコード全文のアップってし辛いのでヤメました(汗)。整形がめんどくさいだけです。ごめんなさい。

| | Comments (0) | TrackBack (0)

エクスプローラの設定に従ったファイルの列挙

あるプログラムの発注元から、

「ファイルの列挙方法は、エクスプローラの設定(ツール-フォルダオプション)に従うようにしてください」

なんて仕様が飛び出してきました。ユーザーから見れば、確かに一番混乱が少なく単純な列挙方法ではあります。

エクスプローラの表示とあわせるなんてのは、極々普通の要求に思えるので簡単に実現できるかと思いきや、そう容易くできないことが判明しました。

まず、エクスプローラと同じファイルの列挙方法なんてのが用意されていません。この時点で嫌な予感がしてきます。

次に、エクスプローラの設定値を取ってくる関数を探すと SHGetSettings という関数が用意されていました。

でも、このAPIってWindows95とかにも対応してるんで、Windows2000で拡張された「スーパー隠しファイル(SuperHidden)」には対応してないことが判明します。まあ、スーパー隠しファイルってHiddenでSystemなファイルってだけみたいですけどね。

#実はスーパー隠しファイルを表示するかどうかの設定は、 SHGetSetSettings というAPIでは参照することができるのですが、これはSHELL32.DLLのバージョンが6以上じゃないとExportされていませんでした。MSDNにはバージョン5から用意してると書いてあるんですけどね(涙)。

あれこれつつきまわした結果、エクスプローラのファイル列挙と一致させるのは、かなり大変だということが分かりました。

今からコーディングしてみますが、上手くできたら後でアップしたいと思います。

| | Comments (0) | TrackBack (0)

2004.05.14

スキャニング作業

紙の図面やら書類をスキャニングするときって、私の中では

スキャニング→4点補正→トリミング

という作業は絶対必要だと思ってたんですが、最近はしないそうです。ちょっとというか、かなりビックリ。

そんだけスキャナの精度が上がったかといえば、そういう訳でもないみたいですけどね。

これは、ビジネスチャンスなのだろうか・・・・。うーむ。

| | Comments (0) | TrackBack (0)

2004.04.16

謎のAcrobat Distiller

あるWordファイルをAcrobat Distillerプリンタに出力すると、「フォントを埋め込まない」という設定をしてるにも関わらず、フォントが埋め込まれてしまうという現象が発生し、あれこれと1日Acrobatの設定をいじりまわしていた。

半日ほど費やした結果、設定の面では、どの設定を行なってもフォントが埋め込まれてしまうことは確認。

お手上げかと思われたが、今度はWord文書の内容に着目し、とりあえず文字全部選択して、フォントを変更してみるが、やはり埋め込まれてしまう。今度は、全部消してPDFを作成すると、フォントは埋め込まれない。(当然?)

ということは、文字に問題があるのかということで、文字を一個づつ確認していくと、「丸付きの印」といういかにも怪しそうな文字が付いてるではないか。とにかくこれを削除してPDFを作成してみると・・・・、無事、フォントが埋め込まれずにPDFの作成ができた。

んで、更にこの「丸付き印」という文字を調べると、どうやらShift-JISコード上には存在しない文字のようだ。Unicode上のみ、かろうじて存在している。よって、Shift-JISをベースに動作しているWindows上では、ファイル名称にもできないし、様々なテキスト編集系の操作で利用ができない。なんちゅー文字だ。やれやれ。

しかし、フォント埋め込まないってしてるのに、エラーも出ずに埋め込んじゃうのはどうにかしてほしい。どういうソフトにも言えることだが、例外が発生した場合、その例外をスルーして処理を先に進め、あたかも正常終了したかのように見える不具合が、ソフトウェア的には最悪のトラブルである。

なにはともあれ、この1日の苦労を元に、上記のようなエラー処理をちゃんとしよう(今もちゃんとしてるけど)と改めて誓ったとさ。

| | Comments (0) | TrackBack (4)

2004.04.07

思わず避ける数字

プログラミングしてると、定義域で色んな定義をやります。エラーコードや、動作モードを変更するためのコードなど、様々な数字を使うのですが、重複を避けるため、上から順番に数字をつけて行くのが一般的です。

そんななか、今日思わず避けてしまった数字があります。

#define HOGEHOGE_AAA 664
#define HOGEHOGE_BBB 665
#define HOGEHOGE_BBB 667 //666は避けてます

しかも、ダサダサなコメント付。ああ、わしってなんて弱気なんだ。

| | Comments (0) | TrackBack (1)

2004.04.02

2byte考慮してない

超絶愚痴モード。こんなコードまで発見しました。

  if (szFullPath[strlen(szFullPath)-1]=='\\')
    szFullPath[strlen(szFullPath)-1] = 0;

今から、'\\'を検索しまくって修正しまくってきます。問題は、オーバーフローとかそういう問題だけじゃなかったっぽいです。どおりで、ユーザ先で様々な現象が発生するはずだ・・・。

| | Comments (0) | TrackBack (0)

whileの使い方知らない?

1日出張のため空きましたが、今日もAさんのプログラムをメンテナンスしてました。

どうやら、

 while(条件){
  //処理A
 }

というのは知ってるけれども、

 if(条件A){
  do{
   //処理A
  }while(条件B);
 }

というのは知らないっぽいです。つまり、

 if(条件A){
  //処理A
  while(条件B){
   //処理A
  }
 }

という処理を何個もしてました。しかも処理Aの部分が30行ぐらいあるんです。もう、メンテナンスする気力が・・・。

| | Comments (0) | TrackBack (0)

2004.03.31

オーバーフロー続き

下のオーバーフローのAさんの件、ファイルサイズの計算部分の話だったのですが、更に先に進んでバグつぶしをしてると、凄いコードにぶつかりました。ファイルサイズ計算は、オーバーフロー(桁あふれ)を防ぐために、WindowsのAPIでは nFileSizeHigh と nFileSizeLow のように溢れても正確な計算ができるように考慮されています。

さて、問題となるのは、このHighとLowを利用して、正確なファイルサイズを計算するコード部分です。

私は単純に、この部分の計算を「((double)nFileSizeHigh * (MAXDWORD+1)) + nFileSizeLow」なんて書いてたのですが、Aさんのソースを解読していくと、足しこんでる部分が「(nFileSizeHigh * MAXDWORD) + nFileSizeLow」なんてなってました。

まあ、相変わらずオーバーフローしてる部分は、多分勘違いだろうから良いとして、なんで、私と計算式が違うんだ。私が間違ってるのか?(←実はめっちゃ弱きな人)

心配になって、MSDNを紐解いて見ると、私のコード(MAX+1を掛ける方)が正解でした。良かった良かった。良く考えりゃ、溢れたんだから、最大値+1を掛けないとダメなのは当たり前ですよね。

しかし、なんでこんな単純なミスをしてるんだろうと思って、ネットで検索をしてみると、Aさんと同じ間違いしてる人が思いの他沢山居るんですね。ビックリしました。

| | Comments (0) | TrackBack (0)

オーバーフローチェック

今日発覚した、Aさん(仮称)が作った間抜けなプログラム。

Aさんは、ある数 a とある数 b を足してオーバーフローしてるかどうかのチェックというのをやるプログラムを作らなくてはなりません。そこで、Aさんは、以下のようなチェックを行ないました。


if((a+b)>MAXDWORD){
//オーバーフロー時の処理
}else{
//オーバーフロー時じゃない処理
}
//※MAXDWORDはDWORDが保持できる最大の数


上記は思いっきりバグってます。ミスに気付きますか?試しに、以下のコードを実行してみましょう。

DWORD a = MAXDWORD - 100;
DWORD b = 101;

if((a+b)>MAXDWORD){
printf("オーバーフローだよ");
}else{
printf("オーバーフローじゃないよ");
}



結果はどう表示されたでしょうか。

やってみれば分かりますが、結果は「オーバーフローじゃないよ」と表示されます。これは、異常(オーバーフロー)になるかどうかの判断を、異常(オーバーフロー)が起こった結果で行なっているために発生します。

つまり、比較する前段階(a+b)のところで「オーバーフロー」が発生してしまいますから、オーバーフローした結果でオーバーフローするかどうかを判断してることになります。意味ありませんね。(^^;

こういった場合のチェックは、より大きな数の計算ができる変数に置き換えるか、意図した結果にならないというチェックをするしかありません。どちらを使うかは好みによるでしょう。

■大きな変数を使う方法
if(((double)a+b)>MAXDWORD){
//オーバーフロー時の処理
}else{
//オーバーフロー時じゃない処理
}

■意図した結果にならないことを証明する方法(足した結果が足す前より小さい)
if((a+b)<a){
//オーバーフロー時の処理
}else{
//オーバーフロー時じゃない処理
}

こういう不具合って、実行時に発覚するので性質が悪いです。しかも、本人はちゃんとしてるつもりだったりするから、なおのこと悪い。今日は、上記不具合で振り回されてます。私だけじゃなくて、ユーザーさんも。本当にトホホです。

#念のため、Aさんは私ではありません。

| | Comments (0) | TrackBack (0)

2004.03.10

BCBにおいてActiveXフォームを安全だとマークする方法

作成したActiveXフォームをIE上で動作させると、「安全だとマークされてない」とか文句を言われます。セキュリティ設定を変更すれば見れるのですが、これでは商品になりません。

そこで、安全だとマークする方法を探すと、めっちゃ簡単でした。

やることは2つだけです。

  1. TXXXImplクラスの宣言部にIObjectSafetyを継承するコードを突っ込む
    多重継承にするわけです。VCLではご法度な多重継承ですが、純粋なC++では問題なく多重継承できますので、以下のように変更します。(ここでは、テスト用に作成したデフォルトのクラス名TActiveFormXImplという名前を使ってます)

    (変更前)
    class ATL_NO_VTABLE TActiveFormXImpl:
     VCLCONTROL_IMPL(TActiveFormXImpl, ActiveFormX, TActiveFormX, IActiveFormX, DIID_IActiveFormXEvents)

    (変更後)
    class ATL_NO_VTABLE TActiveFormXImpl:
     VCLCONTROL_IMPL(TActiveFormXImpl, ActiveFormX, TActiveFormX, IActiveFormX, DIID_IActiveFormXEvents),
     public IObjectSafetyImpl<TActiveFormXImpl, INTERFACESAFE_FOR_UNTRUSTED_CALLER>

    注意点は一つだけです。IObjectSafetyImplはクラステンプレートになっているので、第一パラメータのクラス名を、継承させるクラス名に変更して記述すること。


  2. インターフェースをCOMマップに追加
    BEGIN_COM_MAPの行を探し、END_COM_MAP行までの間に
    VCL_CONTROL_COM_INTERFACE_ENTRIES(IObjectSafety)
    という行を突っ込む

    (変更前)
    BEGIN_COM_MAP(TActiveFormXImpl)
     VCL_CONTROL_COM_INTERFACE_ENTRIES(IActiveFormX)
    END_COM_MAP()

    (変更後)
    BEGIN_COM_MAP(TActiveFormXImpl)
     VCL_CONTROL_COM_INTERFACE_ENTRIES(IActiveFormX)
     VCL_CONTROL_COM_INTERFACE_ENTRIES(IObjectSafety)
    END_COM_MAP()


こんな簡単なことでマークできてしまいます。実質追加したコード量はたったの2行(笑)。ちなみに、このActiveXコントロール内では、ローカルファイルへの操作(アクセス、作成、削除、変更)はバリバリ行なっています。

これって、安全なのでしょうか?

参照:MSDN 手順 7: Web ページへのコントロールの配置

| | Comments (0) | TrackBack (1)

2004.03.05

BCBのTVariantでバイナリデータを扱う場合

TMemoryStreamなどで蓄えているバイナリをCOMインターフェースでやり取りする際など、VARIANT型にしないといけないのですが、これが一筋縄ではいきません。まあ、BCBを使ってるのでVARIANT型自体はTVariantというクラスでラッピングされているため、非常に楽に扱えます。

最初、普通に

TVariant Variant = (char*)MemoryStream->Memory;

なんてしてみましたが、CHAR配列扱いなので、'\0'が出たところで切られてしまいます。当たり前の結果ですね^^;。
こんなたわけたコードを書いてるのは、VARIANT型なんて今まで触ったことなかったためです。つまり、調べるのがめんどくさいってことですね。日本語の情報なんて、MSDN内にもありませんし。

まあ、横着こくのはそのぐらいにして、基本に戻り、HELPとヘッダーを調べていくと、どうやらSafeArrayなるものを利用すればいけそうだということが分かりました。そこまで分かれば、後は早いもんです。Webでちゃちゃっと検索して、MSDNで関数の意味調べて・・・。

結果としては以下のようにやればOK。

SAFEARRAYBOUND saBound ={MemoryStream->Size};
SAFEARRAY* pSafeArray = SafeArrayCreate( VT_UI1, 1, &saBound );

PVOID pvData;
SafeArrayAccessData( pSafeArray, &pvData );
memcpy( pvData, this->m_ZipMemory->Memory, this->m_ZipMemory->Size );
SafeArrayUnaccessData( pSafeArray );

TVariant varTmp(pSafeArray);
//処理
SafeArrayDestroy(pSafeArray);

参考サイト:なんちゃってCOMプログラミング

| | Comments (0) | TrackBack (1)

2004.03.04

レジストリのアクセス権

今日遭遇した不可思議なユーザの環境だが、

HKEY_LOCAL_MACHINE\Software

のAdministratorのアクセス許可が外れているケースが存在する。

ここのアクセス許可が外れていると、インストール時にAdministratorからアクセスできないレジストリが作成されてしまい、インストール後の実行時にエラーが発生することとなる。

一体、どういう状況で上記レジストリのアクセス権がいじられるのだろうか・・・。誰か情報知ってたら教えてください。ちょっとだけググってみたけど分かりませんでした。

というか、こんな出鱈目な環境にインストールできなくて、開発員が直接電話して解決できたのに感謝の言葉もなく、「最初から教えてくれよ。おかげで4時間もかかったよ。」なんて憎まれ口を叩かれた後輩のH君はかわいそうです。

| | Comments (0) | TrackBack (0)

Borland C++ Builder5のライセンス同意

訳あって、Borland C++ Builder5 Ent版を再インストールしたのだが、インストール途中に「ライセンスに同意するか?」という問いかけがあり、今まで必ず「同意する」ボタンを押してたのだが、誤って「同意しない」を押してしまった。

しかし、画面は先に進み、何の問題もなくインストールできるようだ。

なるほど、同意しなくてもインストールできるのか・・・。

でも、インストールが正常に終わったように見えて、まともにインストールされずに意味不明なエラーで悩むようなことがあると嫌なので、もう一度戻って「同意する」をクリックしてインストールを完了した私。仕事じゃなく、趣味の世界なら、間違いなく同意しないで先に進めて楽しんだのだろうが。個人で購入できる値段じゃないもんな・・・。

| | Comments (0) | TrackBack (0)

2004.03.03

ActiveXコントロールのIE上でのModal表示

新しいことをやるときってのは、意欲に燃えるもんです。というわけで、偶には、もろプログラマなネタを。

最近、単純なWindowsアプリケーションではなくIE上で動作させるActiveXコントロールを作成しています。このActiveXコントロール自体はBCBで作成してるんですが、このActiveXコントロールからモーダルダイアログを表示すると、一見Modalに見えて、実はModalじゃないという不思議な現象がおきます。

それを回避するコードが以下

void __fastcall TActiveXTest::Button1Click(TObject *Sender)
{
if(Application->Handle==NULL) Application->CreateHandle();
::SetParent(
Application->Handle,
GetParent(Handle)
);

Form1 = new TForm1(Application);
Form1->ShowModal();
delete Form1;
}

エラー処理とかおざなりですが、大体こんな感じでいけます。お試しあれ。

| | Comments (0) | TrackBack (0)