Могу ли я перекомпилировать файлы .PAS, используемые в Delphi IDE? - PullRequest
4 голосов
/ 07 октября 2009

Я знаком с статьей Джеффа Этвуда о том, что ошибки всегда являются ошибкой программиста , но я считаю, что действительно и действительно нашел ошибку в .pas-файле Delphi.

В частности, я использую Delphi 2007, и ошибка находится в строке 955 файла DBCommon.pas, который на моей машине находится здесь:

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» имеет значение ноль, то мы пытаемся получить доступ к индексу -1 DataSet.Fields, что приводит к ошибке индекса списка за пределами границ.

Эта ошибка не возникает для пользователя, потому что она обрабатывается до того, как она поднимется так высоко, но каждый раз, когда это происходит, чрезвычайно раздражает прерывание отладчика.

Я мог бы «Игнорировать этот тип исключения», но ошибки Index of the bounds достаточно распространены, и я не хочу их игнорировать повсеместно.

Ситуация, при которой FieldIndex равен нулю, возникает, когда у вас есть оператор SELECT, в котором ORDER BY содержит функцию, как в:

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 с моим исправлением, и если да, то как?

Ответы [ 7 ]

12 голосов
/ 08 октября 2009

Вероятно, вы можете поместить dbcommon.pas в каталог вашего проекта. Затем он будет скомпилирован вместе с остальной частью проекта.

4 голосов
/ 08 октября 2009

Вы можете, но часто вам не нужно. Перекомпиляция модуля 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. Он не является общедоступным, поэтому вам необходимо либо объявить его в интерфейсе устройства, либо скопировать его в свой модуль. Тогда вы можете назвать это так же, как код Мадши выше:

var
  Old_GetIndexForOrderBy_Data: TOverwrittenData;

OverwriteProcedure(@DBCommon.GetIndexForOrderBy,
                   @Fixed_GetIndexForOrderBy,
                   @Old_GetIndexForOrderBy_Data);
4 голосов
/ 08 октября 2009

Смотрите предыдущие ответы о том, как создать ситуацию, когда вы можете перекомпилировать модифицированный исходный код VCL. Однако я хотел бы добавить, что вы серьезно рассматриваете возможность управления своими изменениями в вашей системе управления изменениями с использованием шаблона SCM «Vendor Branch».

Проще говоря (используя SVN в качестве справочного материала):

  • Создание «исходной» копии оригинальных файлов, предоставленных поставщиком. Это ваша "нетронутая" справочная копия.

  • Создание ветви, представляющей эту первоначальную копию (например, «2009» для версии VCL Delphi 2009)

  • создать дополнительную ветку в отдельной папке "vendor library". Это копия библиотеки, на которую вы должны ссылаться в своих проектах

  • любые изменения источника поставщика производятся в ветке "vendor library".

  • когда поставщик предоставляет новую версию библиотеки, вы регистрируете новую версию в проекте «source source» и создаете новую ветвь для новой версии.

Вы можете легко изменить версии поставщика. Но что более важно (с SubVersion и, возможно, с другими системами SCM), вы также должны иметь возможность просто объединить (то есть автоматически) новый источник поставщика с вашей ветвью "библиотеки поставщиков", чтобы легко включать изменения поставщика с вашими собственными изменениями.

Все это описано гораздо лучше, чем я описал в превосходной книге О'Рейли: "Контроль версий с SubVersion"

ОБРАТИТЕ ВНИМАНИЕ, однако, что утилита «loaddirs», упомянутая в этой книге, больше не поддерживается из-за проблем с авторским правом, поэтому обновление «отбрасывания поставщиков» в настоящее время выполняется вручную, но это происходит нечасто и не является серьезным бременем.

Мы сами используем этот шаблон, хотя в случае VCL мы не храним полную копию исходного дерева VCL в нашей «базе данных поставщика» или «библиотеке поставщика», а вместо этого отслеживаем только измененные и зависимые единицы , Для других библиотек, управляемых в ветке поставщика, мы обычно поддерживаем полные копии, но решили, что это не нужно для VCL.

Однако мы только что внедрили этот шаблон, поэтому мы все же можем решить, что нам нужно использовать более комплексный подход и с VCL.

YMMV

2 голосов
/ 08 сентября 2010

«Я знаком со статьей Джеффа Этвуда о том, что ошибки всегда являются ошибкой программиста, но я считаю, что действительно и действительно нашел ошибку в файле Delphi .pas»

Ты шутишь? С Delphi ты всегда сначала обвиняешь Borland :) Что-то странное, зайдите в Google и посмотрите, не является ли это ошибкой Delphi. Только если не удается найти аналогичные отчеты, которые вы размещаете на сайте, и построчно проверяйте свой код.

После переустановки Delphi я должен исправить исходные файлы PAS в 6 (шести) местах. Есть тонны ошибок, которые появляются на новой установке Delphi и могут быть легко воспроизведены. Delphi (тот, который мы все любим) полон ошибок. Вокруг этого создана целая история. Есть очень много людей, выпускающих внешние патчи (такие как http://andy.jgknet.de/blog/?page_id=288) и Borland / Imprise / GoGear / Embarcadero продолжают игнорировать их. Это удивительно, что они включили FastMM в свой выпуск.

Во всяком случае, я перекомпилировал эти файлы PAS и теперь заменяю оригинальные DCU исправленными.

2 голосов
/ 08 октября 2009

В нашем дереве исходного кода проекта есть папка VCL, в которую мы помещаем копии исходного кода VCL, которые мы хотим немного изменить. Ваш пример - хороший кандидат для того же. Вам нужно будет изменить путь поиска для своего проекта так, чтобы «ваша» папка VCL находилась на вашем пути раньше, чем «исходные» папки в вашей установке Delphi. Вы также можете обнаружить, что если вы скопируете один исходный модуль VCL и измените его, вам также придется скопировать другие исходные модули VCL в «вашу» папку, которая может быть зависимостью.

Наша причина для этого состоит в том, что мы хотим, чтобы наши сборки имели нулевые подсказки и предупреждения компилятора. Некоторые части источника VCL не свободны от подсказок и предупреждений.

1 голос
/ 20 января 2014

Вы можете установить: DataSetProvider.Option.poRetainServerOrder = True

1 голос
/ 08 октября 2009

Просто - да.Используя один из приведенных выше ответов [Том или Коннор].Скопируйте DBCommon.pas в папку вашего проекта, а не редактируйте оригинал.Это не затрагивает другие проекты и компиляции, поскольку не будет в пути.

...