5

エラーが常にプログラマーのせいであるというJeffAtwoodの記事はよく知っていますが、Delphiの.pasファイルにバグを本当に本当に見つけたと思います。

具体的には、Delphi 2007を使用していますが、エラーはDBCommon.pasファイルの955行目にあります。このファイルは、私のマシンでは次の場所にあります。

C:\ program files \ codegear \ rad studio \ 5.0 \ source \ Win32 \ db \ DBCommon.pas

そしてコードはこれです:

...
  FieldIndex := StrToInt(Token);
  if DataSet.FieldCount >= FieldIndex then
    LastField := DataSet.Fields[FieldIndex-1].FieldName else
...

「Token」の値がゼロの場合、DataSet.Fieldsのインデックス-1にアクセスしようとすると、リストインデックスの範囲外エラーが発生します。

このエラーは、その高さになる前に処理されるため、ユーザーには発生しませんが、これが発生するたびにデバッガーが中断するのは非常に苛立たしいことです。

「この例外タイプを無視する」こともできますが、インデックスの範囲外エラーは十分に一般的であるため、普遍的に無視したくありません。

FieldIndexがゼロになる状況は、次のように、ORDERBYに関数が含まれているSELECTステートメントがある場合です。

ORDER BY
  CASE WHEN FIELD1 = FIELD3 THEN 1 ELSE 2 END
 ,CASE WHEN FIELD2 = FIELD4 THEN 1 ELSE 2 END

DBCommon.pasのバグを修正できますが、Delphiはそれ自体を再コンパイルせず、変更は有効になりません。.DCUファイルの名前を変更すると、「DBCommon.dcu」が見つからないと文句を言うだけです。

だから(最後に)私の質問は:DBCommon.pasを自分の修正で再コンパイルできますか?もしそうなら、どのように?

4

7 に答える 7

12

おそらくdbcommon.pasをプロジェクトディレクトリに置くことができます。その後、プロジェクトの残りの部分と一緒にコンパイルされます。

于 2009-10-07T20:07:07.253 に答える
4

変更されたVCLソースを再コンパイルできる状況を作成する方法については、以前の回答を参照してください。ただし、「ベンダーブランチ」SCMパターンを使用して、変更管理システムで変更を管理することを真剣に検討していることを付け加えておきます。

簡単に言えば(SVNを参照として使用):

  • 元のベンダー提供ファイルの「ベンダーソース」コピーを作成します。これはあなたの「手付かずの」リファレンスコピーです。

  • その元のコピーを表すブランチを作成します(たとえば、Delphi 2009バージョンのVCLの場合は「2009」)。

  • 別の「ベンダーライブラリ」フォルダにさらにブランチを作成します。これは、プロジェクトで参照する必要があるライブラリのコピーです。

  • ベンダーソースへの変更は、「ベンダーライブラリ」ブランチで行われます。

  • ベンダーがライブラリの新しいバージョンを提供する場合、「ベンダーソース」プロジェクトに新しいバージョンをチェックインし、新しいバージョンの新しいブランチを作成します。

その後、ベンダーのリビジョンを簡単に比較できます。しかし、もっと重要なことは(SubVersion、場合によっては他のSCMシステムを使用して)、新しいベンダーソースを「ベンダーライブラリ」ブランチと単純に(つまり自動的に)マージして、ベンダーの変更を独自の変更に簡単に組み込むことができるようにすることです。

これはすべて、優れたO'Reillyの本「SubVersionを使用したバージョン管理」で行ったよりもはるかによく説明されています。

ただし、その本で言及されている「loaddirs」ユーティリティは著作権の問題によりサポートされなくなったため、「ベンダードロップ」の更新は現在手動で行っていますが、これはまれにしか発生せず、大きな負担にはなりません。

このパターンを自分たちで使用していますが、VCLの場合、VCLソースツリー全体の完全なコピーを「ベンダーソース」または「ベンダーライブラリ」に保持するのではなく、変更された依存ユニットのみを追跡します。ベンダーブランチの下で管理されている他のライブラリの場合、通常は完全なコピーを維持しますが、これはVCLには必要ないと判断しました。

ただし、このパターンを実装したばかりなので、VCLでもより包括的なアプローチをとる必要があると判断する可能性があります。

ymmv

于 2009-10-08T00:46:27.560 に答える
4

できますが、多くの場合、そうする必要はありません。VCLユニットを再コンパイルするということは、ユニットのインターフェイスを変更したか、コンパイラが混乱してインターフェイスを変更したと見なしたために、残りのすべてのVCLユニットを再コンパイルすることを意味ます。VCLユニットを再コンパイルすると、Delphiのランタイムパッケージを再コンパイルできないため、ほとんどのランタイムパッケージを使用する可能性も排除されます。

再コンパイルする代わりに、ランタイムパッチを使用できます。TNT Unicodeコントロールでこのメソッドを使用しましたが、Madshiは、関数を独自の実装に置き換える方法も提供します。DBCommon.GetIndexForOrderByの実装を独自のユニットにコピーして修正を行う場合は、次のコマンドを使用して、VCLバージョンに独自のパッチを適用できます。

var
  Old_GetIndexForOrderBy: Pointer;

HookCode(@DBCommon.GetIndexForOrderBy,
         @Fixed_GetIndexForOrderBy,
         Old_GetIndexForOrderBy,
         0);

Tnt Unicodeライブラリを使用OverwriteProcedureして、TntSystemユニットでルーチンを見つけます。公開されていないため、ユニットインターフェイスで宣言するか、独自のユニットにコピーする必要があります。次に、上記のMadshiコードのように呼び出すことができます。

var
  Old_GetIndexForOrderBy_Data: TOverwrittenData;

OverwriteProcedure(@DBCommon.GetIndexForOrderBy,
                   @Fixed_GetIndexForOrderBy,
                   @Old_GetIndexForOrderBy_Data);
于 2009-10-08T04:38:25.540 に答える
2

プロジェクトソースツリーの下にVCLというフォルダーがあり、そこに少し変更したいVCLソースのコピーを配置します。あなたの例は同じことをするための良い候補です。プロジェクトの検索パスを変更して、「your」VCLフォルダーがDelphiインストールの「Source」フォルダーよりもパス上にあるようにする必要があります。また、1つのVCLソースユニットをコピーして変更すると、他のVCLソースユニットも依存関係のある「your」フォルダにコピーする必要がある場合があります。

これを行う理由は、ビルドにコンパイラのヒントと警告をゼロにするためです。VCLソースには、ヒント/警告がない部分がいくつかあります。

于 2009-10-07T20:17:53.360 に答える
2

「エラーが常にプログラマーのせいであるというJeffAtwoodの記事はよく知っていますが、Delphiの.pasファイルにバグを本当に本当に見つけたと思います。」

冗談ですか?Delphiを使用すると、常に最初にBorlandのせいになります:)何かがおかしいので、Googleにアクセスして、Delphiのバグかどうかを確認してください。同様のレポートが見つからない場合にのみ、サイトを特定してコードを1行ずつ確認してください。

Delphiを再インストールした後、元のPASファイルを6か所にパッチする必要があります。Delphiの新規インストールで発生し、簡単に再現できるバグがたくさんあります。Delphi(私たちみんなが大好きなもの)はバグでいっぱいです。これを中心に作成された全体の歴史があります。外部パッチ( http://andy.jgknet.de/blog/?page_id=288など)をリリースする人は非常に多く、Borland / Imprise / GoGear/Embarcaderoはそれらを無視し続けています。彼らがリリースにFastMMを含めたのは本当に不思議です。

とにかく、私はそれらのPASファイルを再コンパイルし、今は元のDCUをパッチを適用したものに置き換えています。

于 2010-09-08T06:57:22.790 に答える
1

単純に-はい。上記の回答のいずれかを使用する[トムまたはコナーによる]。オリジナルを編集するのではなく、DBCommon.pasをプロジェクトフォルダにコピーします。これにより、他のプロジェクトやコンパイルはパス上にないため、影響を受けません。

于 2009-10-07T20:42:26.433 に答える
1

次の設定を行うことができます。 DataSetProvider.Option.poRetainServerOrder = True

于 2014-01-20T01:52:45.753 に答える