Ошибка Β«Unsatisfied Forward or External DeclarationΒ»** β€” ΠΎΠ΄Π½Π° ΠΈΠ· самых распространённых ΠΈ ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ Π·Π°ΠΏΡƒΡ‚Π°Π½Π½Ρ‹Ρ… ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ, с ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌΠΈ ΡΡ‚Π°Π»ΠΊΠΈΠ²Π°ΡŽΡ‚ΡΡ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ Π½Π° Delphi. Она Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π΅Ρ‚ Π½Π° этапС компиляции ΠΈ часто оставляСт Π½ΠΎΠ²ΠΈΡ‡ΠΊΠΎΠ² Π² растСрянности: компилятор отказываСтся ΡΠΎΠ±ΠΈΡ€Π°Ρ‚ΡŒ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚, ΡΡΡ‹Π»Π°ΡΡΡŒ Π½Π° Β«Π½Π΅ΡƒΠ΄ΠΎΠ²Π»Π΅Ρ‚Π²ΠΎΡ€Ρ‘Π½Π½ΠΎΠ΅Β» объявлСниС, Π½ΠΎ ΠΏΡ€ΠΈ этом Π½Π΅ всСгда ясно, ΠΊΠ°ΠΊΠΎΠ΅ ΠΈΠΌΠ΅Π½Π½ΠΎ объявлСниС Π²Ρ‹Π·Π²Π°Π»ΠΎ сбой. Π’ ΠΎΡ‚Π»ΠΈΡ‡ΠΈΠ΅ ΠΎΡ‚ синтаксичСских ошибок, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ ΡƒΠΊΠ°Π·Ρ‹Π²Π°ΡŽΡ‚ Π½Π° ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΡƒΡŽ строку ΠΊΠΎΠ΄Π°, эта ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° Ρ‚Ρ€Π΅Π±ΡƒΠ΅Ρ‚ Π³Π»ΡƒΠ±ΠΎΠΊΠΎΠ³ΠΎ понимания ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΠΎΠ² прямых (forward) ΠΈ Π²Π½Π΅ΡˆΠ½ΠΈΡ… (external) объявлСний Π² Object Pascal.

Π’ этой ΡΡ‚Π°Ρ‚ΡŒΠ΅ ΠΌΡ‹ Ρ€Π°Π·Π±Π΅Ρ€Ρ‘ΠΌ всС Π²ΠΎΠ·ΠΌΠΎΠΆΠ½Ρ‹Π΅ ΠΏΡ€ΠΈΡ‡ΠΈΠ½Ρ‹ ошибки, ΠΎΡ‚ Ρ‚Ρ€ΠΈΠ²ΠΈΠ°Π»ΡŒΠ½Ρ‹Ρ… ΠΎΠΏΠ΅Ρ‡Π°Ρ‚ΠΎΠΊ Π΄ΠΎ слоТных случаСв с цикличСскими зависимостями ΠΌΠ΅ΠΆΠ΄Ρƒ модулями. Π’Ρ‹ ΡƒΠ·Π½Π°Π΅Ρ‚Π΅, ΠΊΠ°ΠΊ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎ ΠΎΡ€Π³Π°Π½ΠΈΠ·ΠΎΠ²Ρ‹Π²Π°Ρ‚ΡŒ forward-объявлСния, Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ с external-Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΈΠ²Π°ΠΌΠΈ, ΠΈ ΠΏΠΎΡ‡Π΅ΠΌΡƒ ΠΈΠ½ΠΎΠ³Π΄Π° ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° кроСтся Π½Π΅ Π² вашСм ΠΊΠΎΠ΄Π΅, Π° Π² настройках ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π° ΠΈΠ»ΠΈ Π΄Π°ΠΆΠ΅ Π² вСрсии компилятора. ΠœΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π» Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠΎΠ»Π΅Π·Π΅Π½ ΠΊΠ°ΠΊ Π½Π°Ρ‡ΠΈΠ½Π°ΡŽΡ‰ΠΈΠΌ программистам, Ρ‚Π°ΠΊ ΠΈ ΠΎΠΏΡ‹Ρ‚Π½Ρ‹ΠΌ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ°ΠΌ, ΡΡ‚ΠΎΠ»ΠΊΠ½ΡƒΠ²ΡˆΠΈΠΌΡΡ с Π½Π΅ΠΎΡ‡Π΅Π²ΠΈΠ΄Π½Ρ‹ΠΌΠΈ Π±Π°Π³Π°ΠΌΠΈ Π² ΠΊΡ€ΡƒΠΏΠ½Ρ‹Ρ… ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°Ρ….

Π§Ρ‚ΠΎ ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚ ошибка Β«Unsatisfied Forward or External DeclarationΒ»?

Начнём с Ρ€Π°ΡΡˆΠΈΡ„Ρ€ΠΎΠ²ΠΊΠΈ Ρ‚Π΅Ρ€ΠΌΠΈΠ½ΠΎΠ². Π’ Delphi Π΅ΡΡ‚ΡŒ Π΄Π²Π° Ρ‚ΠΈΠΏΠ° объявлСний, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ эту ΠΎΡˆΠΈΠ±ΠΊΡƒ:

  • πŸ”Ή Forward-объявлСния β€” ΠΊΠΎΠ³Π΄Π° Π²Ρ‹ Π·Π°Ρ€Π°Π½Π΅Π΅ ΠΎΠ±ΡŠΡΠ²Π»ΡΠ΅Ρ‚Π΅ класс, ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Ρƒ ΠΈΠ»ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΠ·ΠΆΠ΅ Π΄Π°Ρ‚ΡŒ Π΅Ρ‘ ΠΏΠΎΠ»Π½ΠΎΠ΅ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅. НапримСр:
    type
    

    TMyClass = class; // Forward-объявлСниС

    ...

    TMyClass = class(TObject) // ПолноС ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅

    // рСализация

    end;

  • πŸ”Ή External-объявлСния β€” ΠΊΠΎΠ³Π΄Π° рСализация Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΈΠ»ΠΈ ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Ρ‹ находится Π² Π΄Ρ€ΡƒΠ³ΠΎΠΌ ΠΌΠΎΠ΄ΡƒΠ»Π΅ ΠΈΠ»ΠΈ внСшнСй Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ΅ (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, external 'user32.dll').

Ошибка Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π΅Ρ‚, ΠΊΠΎΠ³Π΄Π° компилятор Π½Π΅ Π½Π°Ρ…ΠΎΠ΄ΠΈΡ‚ ΠΏΠΎΠ»Π½ΠΎΠ³ΠΎ опрСдСлСния для Ρ€Π°Π½Π΅Π΅ объявлСнного элСмСнта ΠΈΠ»ΠΈ Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΡΠ²ΡΠ·Π°Ρ‚ΡŒ Π΅Π³ΠΎ с внСшнСй Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠ΅ΠΉ. ΠŸΡ€ΠΈΡ‡ΠΈΠ½Ρ‹ ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ Ρ€Π°Π·Π½Ρ‹ΠΌΠΈ:

  • πŸ“Œ ΠžΡ‚ΡΡƒΡ‚ΡΡ‚Π²ΡƒΠ΅Ρ‚ ΠΏΠΎΠ»Π½ΠΎΠ΅ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ класса/ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Ρ‹ послС forward.
  • πŸ“Œ ΠžΠΏΠ΅Ρ‡Π°Ρ‚ΠΊΠ° Π² ΠΈΠΌΠ΅Π½ΠΈ ΠΏΡ€ΠΈ ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΠΎΠΌ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠΈ.
  • πŸ“Œ ЦикличСскиС зависимости ΠΌΠ΅ΠΆΠ΄Ρƒ модулями.
  • πŸ“Œ ΠΠ΅ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½Ρ‹Π΅ настройки Π»ΠΈΠ½ΠΊΠΎΠ²Ρ‰ΠΈΠΊΠ° (linker) Π² ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π΅.
  • πŸ“Œ ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹ с путями ΠΊ внСшним Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ°ΠΌ (.dll, .obj).
⚠️ Π’Π½ΠΈΠΌΠ°Π½ΠΈΠ΅: Если Π²Ρ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚Π΅ forward для класса, Π° Π·Π°Ρ‚Π΅ΠΌ Π·Π°Π±Ρ‹Π²Π°Π΅Ρ‚Π΅ Π΄Π°Ρ‚ΡŒ Π΅Π³ΠΎ ΠΏΠΎΠ»Π½ΠΎΠ΅ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅, компилятор Π½Π΅ ΡƒΠΊΠ°ΠΆΠ΅Ρ‚ Π½Π° ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΡƒΡŽ строку с ошибкой. Он просто выдаст ΠΎΠ±Ρ‰Π΅Π΅ сообщСниС ΠΎ Β«Π½Π΅ΡƒΠ΄ΠΎΠ²Π»Π΅Ρ‚Π²ΠΎΡ€Ρ‘Π½Π½ΠΎΠΌ объявлСнии», Ρ‡Ρ‚ΠΎ услоТняСт диагностику.

Π’ΠΈΠΏΠΈΡ‡Π½Ρ‹Π΅ сцСнарии возникновСния ошибки

Рассмотрим Π½Π°ΠΈΠ±ΠΎΠ»Π΅Π΅ частыС ситуации, Π² ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ ΡΡ‚Π°Π»ΠΊΠΈΠ²Π°ΡŽΡ‚ΡΡ с этой ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠΎΠΉ.

1. Π—Π°Π±Ρ‹Ρ‚ΠΎΠ΅ ΠΏΠΎΠ»Π½ΠΎΠ΅ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ послС forward

ΠšΠ»Π°ΡΡΠΈΡ‡Π΅ΡΠΊΠΈΠΉ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ β€” объявлСниС класса с forward, Π½ΠΎ Π±Π΅Π· ΠΏΠΎΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΉ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ:

type

TMyForm = class; // Forward

// ... Π΄Ρ€ΡƒΠ³ΠΎΠΉ ΠΊΠΎΠ΄ ...

// А Π³Π΄Π΅ ΠΆΠ΅ ΠΏΠΎΠ»Π½ΠΎΠ΅ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ TMyForm? Π•Π³ΠΎ Π½Π΅Ρ‚!

РСшСниС: всСгда провСряйтС, Ρ‡Ρ‚ΠΎ послС forward-объявлСния Π΅ΡΡ‚ΡŒ ΠΏΠΎΠ»Π½ΠΎΠ΅ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ с Ρ‚Π΅ΠΌ ΠΆΠ΅ ΠΈΠΌΠ΅Π½Π΅ΠΌ ΠΈ Π² Ρ‚ΠΎΠΌ ΠΆΠ΅ ΠΌΠΎΠ΄ΡƒΠ»Π΅.

2. ΠžΠΏΠ΅Ρ‡Π°Ρ‚ΠΊΠΈ Π² ΠΈΠΌΠ΅Π½Π°Ρ…

ЧСловСчСский Ρ„Π°ΠΊΡ‚ΠΎΡ€ Π½ΠΈΠΊΡ‚ΠΎ Π½Π΅ отмСнял. НапримСр:

type

TMyClass = class; // Forward

// ...

TMyKlass = class(TObject) // ΠžΠΏΠ΅Ρ‡Π°Ρ‚ΠΊΠ°: MyClass vs MyKlass

// рСализация

end;

ΠšΠΎΠΌΠΏΠΈΠ»ΡΡ‚ΠΎΡ€ воспринимаСт TMyClass ΠΈ TMyKlass ΠΊΠ°ΠΊ Ρ€Π°Π·Π½Ρ‹Π΅ сущности, поэтому Π²Ρ‹Π΄Π°Ρ‘Ρ‚ ΠΎΡˆΠΈΠ±ΠΊΡƒ.

3. ЦикличСскиС зависимости ΠΌΠΎΠ΄ΡƒΠ»Π΅ΠΉ

Если Unit1 ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ Unit2, Π° Unit2 β€” Unit1, ΠΈ ΠΏΡ€ΠΈ этом Π΅ΡΡ‚ΡŒ forward-объявлСния, компилятор ΠΌΠΎΠΆΠ΅Ρ‚ Β«Π·Π°ΠΏΡƒΡ‚Π°Ρ‚ΡŒΡΡΒ». НапримСр:

// Unit1.pas

unit Unit1;

interface

uses Unit2;

type

TClass1 = class; // Forward

// Unit2.pas

unit Unit2;

interface

uses Unit1;

type

TClass2 = class(TClass1) // Ошибка: TClass1 Π΅Ρ‰Ρ‘ Π½Π΅ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Ρ‘Π½!

РСшСниС: Ρ€Π°Π·Ρ€Ρ‹Π²Π°ΠΉΡ‚Π΅ цикличСскиС зависимости ΠΈΠ»ΠΈ выноситС ΠΎΠ±Ρ‰ΠΈΠ΅ Ρ‚ΠΈΠΏΡ‹ Π² Ρ‚Ρ€Π΅Ρ‚ΠΈΠΉ ΠΌΠΎΠ΄ΡƒΠ»ΡŒ.

πŸ“Š Π‘ ΠΊΠ°ΠΊΠΎΠΉ частотой Π²Ρ‹ ΡΡ‚Π°Π»ΠΊΠΈΠ²Π°Π΅Ρ‚Π΅ΡΡŒ с ошибками компиляции Π² Delphi?
  • Часто (СТСнСдСльно)
  • Иногда (СТСмСсячно)
  • Рядко (Ρ€Π°Π· Π² ΠΏΠΎΠ»Π³ΠΎΠ΄Π°)
  • Никогда

Как Π΄ΠΈΠ°Π³Π½ΠΎΡΡ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡƒ: пошаговая инструкция

Если Π²Ρ‹ ΡƒΠ²ΠΈΠ΄Π΅Π»ΠΈ сообщСниС ΠΎΠ± ошибкС, слСдуйтС этому Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌΡƒ:

  1. ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡŒΡ‚Π΅ имя сущности. Π£Π±Π΅Π΄ΠΈΡ‚Π΅ΡΡŒ, Ρ‡Ρ‚ΠΎ имя Π² forward-объявлСнии ΠΈ ΠΏΠΎΠ»Π½ΠΎΠ΅ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ ΡΠΎΠ²ΠΏΠ°Π΄Π°ΡŽΡ‚ символ Π² символ (Π²ΠΊΠ»ΡŽΡ‡Π°Ρ рСгистр!).
  2. Π˜Ρ‰ΠΈΡ‚Π΅ ΠΏΠΎΠ»Π½ΠΎΠ΅ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅. Для классов ΠΎΠ½ΠΎ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±Ρ‹Ρ‚ΡŒ Π² Ρ‚ΠΎΠΌ ΠΆΠ΅ ΠΌΠΎΠ΄ΡƒΠ»Π΅, для ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€/Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ β€” Π»ΠΈΠ±ΠΎ Π² Ρ‚ΠΎΠΌ ΠΆΠ΅ ΠΌΠΎΠ΄ΡƒΠ»Π΅, Π»ΠΈΠ±ΠΎ (Ссли external) Π² связанной Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ΅.
  3. ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€ΠΈΡ‚Π΅ uses. Π£Π±Π΅Π΄ΠΈΡ‚Π΅ΡΡŒ, Ρ‡Ρ‚ΠΎ всС Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Π΅ ΠΌΠΎΠ΄ΡƒΠ»ΠΈ ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π΅Π½Ρ‹, ΠΈ Π½Π΅Ρ‚ цикличСских зависимостСй.
  4. ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡŒΡ‚Π΅ настройки ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°. Для external-ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€ ΡƒΠ±Π΅Π΄ΠΈΡ‚Π΅ΡΡŒ, Ρ‡Ρ‚ΠΎ ΠΏΡƒΡ‚ΠΈ ΠΊ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ°ΠΌ (.dll, .lib) ΡƒΠΊΠ°Π·Π°Π½Ρ‹ Π² Project β†’ Options β†’ Delphi Compiler β†’ Linking.

ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° совпадСния ΠΈΠΌΡ‘Π½ Π² forward ΠΈ ΠΏΠΎΠ»Π½ΠΎΠΌ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠΈ|

Поиск ΠΏΠΎΠ»Π½ΠΎΠ³ΠΎ опрСдСлСния Π² Ρ‚ΠΎΠΌ ΠΆΠ΅ ΠΌΠΎΠ΄ΡƒΠ»Π΅|

Анализ сСкции uses Π½Π° цикличСскиС зависимости|

ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° ΠΏΡƒΡ‚Π΅ΠΉ ΠΊ внСшним Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ°ΠΌ Π² настройках ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°|

ΠŸΡ€ΠΎΡΠΌΠΎΡ‚Ρ€ Π»ΠΎΠ³Π° компиляции Π½Π° Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ подсказки-->

Если ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° Π½Π΅ Ρ€Π΅ΡˆΠ΅Π½Π°, ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ΠΈΡ‚Π΅ ΠΊ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΌΡƒ Ρ€Π°Π·Π΄Π΅Π»Ρƒ с ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½Ρ‹ΠΌΠΈ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°ΠΌΠΈ.

ΠŸΡ€Π°ΠΊΡ‚ΠΈΡ‡Π΅ΡΠΊΠΈΠ΅ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ ΠΈ Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ

Π Π°Π·Π±Π΅Ρ€Ρ‘ΠΌ Ρ€Π΅Π°Π»ΡŒΠ½Ρ‹Π΅ случаи ΠΈΠ· ΠΏΡ€Π°ΠΊΡ‚ΠΈΠΊΠΈ ΠΈ способы ΠΈΡ… исправлСния.

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ 1: Forward-объявлСниС класса Π±Π΅Π· Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ

Ошибка:

type

TDataProcessor = class; // Forward

procedure ProcessData(Data: TDataProcessor); // Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ forward-объявлСниС

// ... Π΄Ρ€ΡƒΠ³ΠΎΠΉ ΠΊΠΎΠ΄ ...

// Π—Π°Π±Ρ‹Π»ΠΈ Π΄Π°Ρ‚ΡŒ ΠΏΠΎΠ»Π½ΠΎΠ΅ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ TDataProcessor!

РСшСниС: Π”ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΡŽ класса:

type

TDataProcessor = class(TObject)

public

procedure Execute;

end;

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ 2: ΠΠ΅ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎΠ΅ использованиС external

Ошибка:

procedure ExternalProc; external 'mylib.dll'; // Ошибка: Π½Π΅ ΡƒΠΊΠ°Π·Π°Π½ΠΎ имя Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π² DLL

// ΠΈΠ»ΠΈ

procedure ExternalProc; external 'mylib.dll' name 'WrongProcName'; // Имя Π½Π΅ совпадаСт с экспортированным

РСшСниС: Π£Π±Π΅Π΄ΠΈΡ‚Π΅ΡΡŒ, Ρ‡Ρ‚ΠΎ:

  • πŸ”Ή Имя Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π² name совпадаСт с экспортированным ΠΈΠΌΠ΅Π½Π΅ΠΌ Π² DLL (ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΡ‚ΡŒ ΡƒΡ‚ΠΈΠ»ΠΈΡ‚ΠΎΠΉ Dependency Walker).
  • πŸ”Ή ΠŸΡƒΡ‚ΡŒ ΠΊ DLL ΡƒΠΊΠ°Π·Π°Π½ Π² настройках ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π° ΠΈΠ»ΠΈ Ρ„Π°ΠΉΠ» Π»Π΅ΠΆΠΈΡ‚ Π² Ρ‚ΠΎΠΉ ΠΆΠ΅ ΠΏΠ°ΠΏΠΊΠ΅, Ρ‡Ρ‚ΠΎ ΠΈ исполняСмый Ρ„Π°ΠΉΠ».

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ 3: ЦикличСскиС зависимости с forward-объявлСниями

Ошибка: Π”Π²Π° модуля ΡΡΡ‹Π»Π°ΡŽΡ‚ΡΡ Π΄Ρ€ΡƒΠ³ Π½Π° Π΄Ρ€ΡƒΠ³Π° Ρ‡Π΅Ρ€Π΅Π· forward:

// ModuleA.pas

unit ModuleA;

interface

uses ModuleB;

type

TClassA = class(TClassB); // Ошибка: TClassB Π΅Ρ‰Ρ‘ Π½Π΅ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Ρ‘Π½!

// ModuleB.pas

unit ModuleB;

interface

uses ModuleA;

type

TClassB = class; // Forward

РСшСниС: ВынСситС ΠΎΠ±Ρ‰ΠΈΠΉ Π±Π°Π·ΠΎΠ²Ρ‹ΠΉ класс Π² Ρ‚Ρ€Π΅Ρ‚ΠΈΠΉ ΠΌΠΎΠ΄ΡƒΠ»ΡŒ ΠΈΠ»ΠΈ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ интСрфСйсы вмСсто наслСдования.

Π’ΠΈΠΏ ошибки ΠŸΡ€ΠΈΡ‡ΠΈΠ½Π° РСшСниС
ΠžΡ‚ΡΡƒΡ‚ΡΡ‚Π²ΡƒΠ΅Ρ‚ ΠΏΠΎΠ»Π½ΠΎΠ΅ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ Π—Π°Π±Ρ‹Π»ΠΈ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ класс/ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Ρƒ послС forward Π”ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΡŽ с ΡΠΎΠ²ΠΏΠ°Π΄Π°ΡŽΡ‰ΠΈΠΌ ΠΈΠΌΠ΅Π½Π΅ΠΌ
ΠžΠΏΠ΅Ρ‡Π°Ρ‚ΠΊΠ° Π² ΠΈΠΌΠ΅Π½ΠΈ Π Π°Π·Π½Ρ‹Π΅ ΠΈΠΌΠ΅Π½Π° Π² forward ΠΈ ΠΏΠΎΠ»Π½ΠΎΠΌ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠΈ Π˜ΡΠΏΡ€Π°Π²ΠΈΡ‚ΡŒ имя, Ρ‡Ρ‚ΠΎΠ±Ρ‹ совпадало ΠΏΠΎΠ»Π½ΠΎΡΡ‚ΡŒΡŽ
ЦикличСскиС зависимости Π”Π²Π° модуля ΡΡΡ‹Π»Π°ΡŽΡ‚ΡΡ Π΄Ρ€ΡƒΠ³ Π½Π° Π΄Ρ€ΡƒΠ³Π° Ρ‡Π΅Ρ€Π΅Π· forward ВынСсти ΠΎΠ±Ρ‰ΠΈΠ΅ Ρ‚ΠΈΠΏΡ‹ Π² Ρ‚Ρ€Π΅Ρ‚ΠΈΠΉ ΠΌΠΎΠ΄ΡƒΠ»ΡŒ
ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹ с external ΠΠ΅ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎΠ΅ имя Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΈΠ»ΠΈ ΠΏΡƒΡ‚ΡŒ ΠΊ DLL ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΈΡ‚ΡŒ экспортированныС ΠΈΠΌΠ΅Π½Π° Π² DLL ΠΈ ΠΏΡƒΡ‚ΠΈ
Настройки Π»ΠΈΠ½ΠΊΠΎΠ²Ρ‰ΠΈΠΊΠ° ΠžΡ‚ΡΡƒΡ‚ΡΡ‚Π²ΡƒΡŽΡ‚ ΠΏΡƒΡ‚ΠΈ ΠΊ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ°ΠΌ Π² опциях ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π° Π”ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ ΠΏΡƒΡ‚ΠΈ Π² Project Options β†’ Linking

РаспространённыС ΠΌΠΈΡ„Ρ‹ ΠΈ заблуТдСния

Π’ΠΎΠΊΡ€ΡƒΠ³ этой ошибки Ρ…ΠΎΠ΄ΠΈΡ‚ ΠΌΠ½ΠΎΠ³ΠΎ ΠΌΠΈΡ„ΠΎΠ². Π Π°Π·Π±Π΅Ρ€Ρ‘ΠΌ самыС популярныС:

⚠️ Π’Π½ΠΈΠΌΠ°Π½ΠΈΠ΅: МногиС Π΄ΡƒΠΌΠ°ΡŽΡ‚, Ρ‡Ρ‚ΠΎ forward-объявлСния Π½ΡƒΠΆΠ½Ρ‹ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ для классов. На самом Π΄Π΅Π»Π΅ ΠΈΡ… ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΈ для ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€/Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ, Ссли ΠΈΡ… рСализация Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠΎΠ·ΠΆΠ΅ Π² Ρ‚ΠΎΠΌ ΠΆΠ΅ ΠΌΠΎΠ΄ΡƒΠ»Π΅. НапримСр:
procedure DoSomething; forward; // Forward для ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Ρ‹

procedure AnotherProc;

begin

DoSomething; // МоТно Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ, хотя Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ Π΅Ρ‰Ρ‘ Π½Π΅Ρ‚

end;

procedure DoSomething; // РСализация

begin

// ΠΊΠΎΠ΄

end;

ΠœΠΈΡ„ 1: «Ошибка всСгда ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ Π½Π° строку с ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠΎΠΉΒ».

Π Π΅Π°Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ: ΠšΠΎΠΌΠΏΠΈΠ»ΡΡ‚ΠΎΡ€ часто Π²Ρ‹Π΄Π°Ρ‘Ρ‚ сообщСниС ΠΎΠ± ошибкС Π² мСстС использования Π½Π΅ΡƒΠ΄ΠΎΠ²Π»Π΅Ρ‚Π²ΠΎΡ€Ρ‘Π½Π½ΠΎΠ³ΠΎ объявлСния, Π° Π½Π΅ Π² мСстС Π΅Π³ΠΎ опрСдСлСния. НапримСр, Ссли Π²Ρ‹ Π·Π°Π±Ρ‹Π»ΠΈ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ класс, ошибка ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΠΎΡΠ²ΠΈΡ‚ΡŒΡΡ Ρ‚Π°ΠΌ, Π³Π΄Π΅ Π²Ρ‹ ΠΏΡ‹Ρ‚Π°Π΅Ρ‚Π΅ΡΡŒ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ Π΅Π³ΠΎ экзСмпляр.

ΠœΠΈΡ„ 2: Β«External Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ с DLLΒ».

Π Π΅Π°Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ: Π”ΠΈΡ€Π΅ΠΊΡ‚ΠΈΠ²Π° external ΠΌΠΎΠΆΠ΅Ρ‚ ΡΡΡ‹Π»Π°Ρ‚ΡŒΡΡ ΠΈ Π½Π° .obj-Ρ„Π°ΠΉΠ»Ρ‹, ΠΈ Π½Π° Π΄Ρ€ΡƒΠ³ΠΈΠ΅ исполняСмыС ΠΌΠΎΠ΄ΡƒΠ»ΠΈ. Π“Π»Π°Π²Π½ΠΎΠ΅ β€” ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎ ΡƒΠΊΠ°Π·Π°Ρ‚ΡŒ ΠΏΡƒΡ‚ΡŒ ΠΈ имя символа.

ΠœΠΈΡ„ 3: «ЦикличСскиС зависимости всСгда приводят ΠΊ этой ошибкС».

Π Π΅Π°Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ: ЦикличСскиС зависимости ΠΌΠΎΠ³ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡƒ, Π½ΠΎ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ссли ΠΎΠ½ΠΈ ΡΠΎΡ‡Π΅Ρ‚Π°ΡŽΡ‚ΡΡ с forward-объявлСниями. ЧистыС цикличСскиС зависимости (Π±Π΅Π· forward) ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ приводят ΠΊ Π΄Ρ€ΡƒΠ³ΠΎΠΉ ошибкС: "Unit X interfaces with unit Y which interfaces with unit X".

πŸ’‘

Если Π²Ρ‹ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚Π΅ с большим ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ΠΎΠΌ, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ инструмСнт Delphi Parser ΠΈΠ»ΠΈ Castalia для Π²ΠΈΠ·ΡƒΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ зависимостСй ΠΌΠ΅ΠΆΠ΄Ρƒ модулями. Π­Ρ‚ΠΎ ΠΏΠΎΠΌΠΎΠΆΠ΅Ρ‚ быстро Π½Π°ΠΉΡ‚ΠΈ цикличСскиС ссылки.

Как ΠΈΠ·Π±Π΅ΠΆΠ°Ρ‚ΡŒ ошибки Π² Π±ΡƒΠ΄ΡƒΡ‰Π΅ΠΌ: Π»ΡƒΡ‡ΡˆΠΈΠ΅ ΠΏΡ€Π°ΠΊΡ‚ΠΈΠΊΠΈ

Π‘Π»Π΅Π΄ΡƒΠΉΡ‚Π΅ этим рСкомСндациям, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΌΠΈΠ½ΠΈΠΌΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ риск ΡΡ‚ΠΎΠ»ΠΊΠ½ΡƒΡ‚ΡŒΡΡ с Β«Unsatisfied Forward or External DeclarationΒ»**:

  • πŸ›  Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ forward осознанно. НС ΠΎΠ±ΡŠΡΠ²ΠΉΡ‚Π΅ всё подряд Ρ‡Π΅Ρ€Π΅Π· forward β€” это услоТняСт ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΡƒ ΠΊΠΎΠ΄Π°. ΠŸΡ€ΠΈΠΌΠ΅Π½ΡΠΉΡ‚Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΊΠΎΠ³Π΄Π° Π΄Π΅ΠΉΡΡ‚Π²ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ Π½ΡƒΠΆΠ½ΠΎ (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, для Π²Π·Π°ΠΈΠΌΠ½ΠΎ рСкурсивных Ρ‚ΠΈΠΏΠΎΠ²).
  • πŸ“‚ Π‘Ρ‚Ρ€ΡƒΠΊΡ‚ΡƒΡ€ΠΈΡ€ΡƒΠΉΡ‚Π΅ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚. Π˜Π·Π±Π΅Π³Π°ΠΉΡ‚Π΅ цикличСских зависимостСй ΠΌΠ΅ΠΆΠ΄Ρƒ модулями. Если Π΄Π²Π° модуля сильно связаны, вынСситС ΠΎΠ±Ρ‰ΠΈΠ΅ Ρ‚ΠΈΠΏΡ‹ Π² Ρ‚Ρ€Π΅Ρ‚ΠΈΠΉ.
  • πŸ” ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠΉΡ‚Π΅ экспорт DLL. ΠŸΡ€ΠΈ Ρ€Π°Π±ΠΎΡ‚Π΅ с external всСгда ΡƒΠ±Π΅Π΄ΠΈΡ‚Π΅ΡΡŒ, Ρ‡Ρ‚ΠΎ функция Π΄Π΅ΠΉΡΡ‚Π²ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ экспортируСтся ΠΈΠ· DLL (ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ Dependency Walker ΠΈΠ»ΠΈ dumpbin).
  • πŸ“ Π”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚ΠΈΡ€ΡƒΠΉΡ‚Π΅ внСшниС зависимости. Если ваш ΠΊΠΎΠ΄ зависит ΠΎΡ‚ Π²Π½Π΅ΡˆΠ½ΠΈΡ… Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊ, оставляйтС ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΈ с вСрсиями ΠΈ путями ΠΊ Ρ„Π°ΠΉΠ»Π°ΠΌ.
  • πŸ”„ Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ Ρ€Π΅Ρ„Π°ΠΊΡ‚ΠΎΡ€ΠΈΠ½Π³. Π‘ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ вСрсии Delphi (начиная с 10.4 Sydney) ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‚ инструмСнты Ρ€Π΅Ρ„Π°ΠΊΡ‚ΠΎΡ€ΠΈΠ½Π³Π°, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΏΠΎΠΌΠΎΠ³Π°ΡŽΡ‚ ΠΈΠ·Π±Π΅ΠΆΠ°Ρ‚ΡŒ ΠΎΠΏΠ΅Ρ‡Π°Ρ‚ΠΎΠΊ Π² ΠΈΠΌΠ΅Π½Π°Ρ….

Для ΠΊΡ€ΡƒΠΏΠ½Ρ‹Ρ… ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ΠΎΠ² ΠΏΠΎΠ»Π΅Π·Π½ΠΎ Π½Π°ΡΡ‚Ρ€ΠΎΠΈΡ‚ΡŒ статичСский Π°Π½Π°Π»ΠΈΠ· ΠΊΠΎΠ΄Π° (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ PascalAnalyzer ΠΈΠ»ΠΈ встроСнных срСдств Delphi). Π­Ρ‚ΠΎ ΠΏΠΎΠΌΠΎΠΆΠ΅Ρ‚ Π²Ρ‹ΡΠ²Π»ΡΡ‚ΡŒ ΠΏΠΎΡ‚Π΅Π½Ρ†ΠΈΠ°Π»ΡŒΠ½Ρ‹Π΅ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹ Π½Π° Ρ€Π°Π½Π½ΠΈΡ… этапах.

ΠŸΠΎΡ‡Π΅ΠΌΡƒ ошибка ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΠΎΡΠ²Π»ΡΡ‚ΡŒΡΡ ΠΏΡ€ΠΈ сборкС ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°, Π½ΠΎ Π½Π΅ ΠΏΡ€ΠΈ компиляции ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠ³ΠΎ модуля?

Π­Ρ‚Π° ситуация Ρ‚ΠΈΠΏΠΈΡ‡Π½Π° для ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ΠΎΠ² с мноТСством ΠΌΠΎΠ΄ΡƒΠ»Π΅ΠΉ. ΠŸΡ€ΠΈ компиляции ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠ³ΠΎ модуля компилятор Π½Π΅ Π²ΠΈΠ΄ΠΈΡ‚ всСй ΠΊΠ°Ρ€Ρ‚ΠΈΠ½Ρ‹ зависимостСй, поэтому ошибка проявляСтся Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΡ€ΠΈ ΠΏΠΎΠ»Π½ΠΎΠΉ сборкС ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°. Π§Π°Ρ‰Π΅ всСго это связано с:

1. ЦикличСскими зависимостями, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π½Π΅ Π²ΠΈΠ΄Π½Ρ‹ Π½Π° ΡƒΡ€ΠΎΠ²Π½Π΅ ΠΎΠ΄Π½ΠΎΠ³ΠΎ модуля.

2. ΠΠ΅ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½Ρ‹ΠΌΠΈ путями ΠΊ внСшним Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ°ΠΌ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΡΡŽΡ‚ΡΡ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π½Π° этапС Π»ΠΈΠ½ΠΊΠΎΠ²ΠΊΠΈ.

3. Ошибками Π² forward-ΠΎΠ±ΡŠΡΠ²Π»Π΅Π½ΠΈΡΡ…, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ΡΡ Π² Π΄Ρ€ΡƒΠ³ΠΈΡ… модулях.

FAQ: ЧастыС вопросы ΠΏΠΎ ошибкС

ΠŸΠΎΡ‡Π΅ΠΌΡƒ компилятор Π½Π΅ ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚, ΠΊΠ°ΠΊΠΎΠ΅ ΠΈΠΌΠ΅Π½Π½ΠΎ объявлСниС Π½Π΅ΡƒΠ΄ΠΎΠ²Π»Π΅Ρ‚Π²ΠΎΡ€Π΅Π½ΠΎ?

Π­Ρ‚ΠΎ ΠΎΡΠΎΠ±Π΅Π½Π½ΠΎΡΡ‚ΡŒ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΠ° forward-объявлСний Π² Delphi. ΠšΠΎΠΌΠΏΠΈΠ»ΡΡ‚ΠΎΡ€ ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ ΠΊΠΎΠ΄ Π² Π΄Π²Π° ΠΏΡ€ΠΎΡ…ΠΎΠ΄Π°: Π½Π° ΠΏΠ΅Ρ€Π²ΠΎΠΌ ΠΎΠ½ собираСт всС объявлСния, Π½Π° Π²Ρ‚ΠΎΡ€ΠΎΠΌ провСряСт ΠΈΡ… Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΡŽ. Если Π½Π° Π²Ρ‚ΠΎΡ€ΠΎΠΌ ΠΏΡ€ΠΎΡ…ΠΎΠ΄Π΅ Ρ‡Ρ‚ΠΎ-Ρ‚ΠΎ Π½Π΅ Π½Π°ΠΉΠ΄Π΅Π½ΠΎ, ΠΎΠ½ Π²Ρ‹Π΄Π°Ρ‘Ρ‚ ΠΎΠ±Ρ‰Π΅Π΅ сообщСниС, Π½ΠΎ Π½Π΅ всСгда ΠΌΠΎΠΆΠ΅Ρ‚ Ρ‚ΠΎΡ‡Π½ΠΎ ΡƒΠΊΠ°Π·Π°Ρ‚ΡŒ источник ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹. Π§Ρ‚ΠΎΠ±Ρ‹ ΡΡƒΠ·ΠΈΡ‚ΡŒ поиск:

  1. ΠŸΠΎΡΠΌΠΎΡ‚Ρ€ΠΈΡ‚Π΅ Π½Π° строку, ΠΊΠΎΡ‚ΠΎΡ€ΡƒΡŽ ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ компилятор β€” Ρ‚Π°ΠΌ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ подсказка.
  2. Π˜Ρ‰ΠΈΡ‚Π΅ послСднСС forward-объявлСниС ΠΏΠ΅Ρ€Π΅Π΄ ошибкой.
  3. ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡŒΡ‚Π΅ ΠΌΠΎΠ΄ΡƒΠ»ΠΈ, ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Ρ‘Π½Π½Ρ‹Π΅ Ρ‡Π΅Ρ€Π΅Π· uses β€” ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ Ρ‚Π°ΠΌ.
МоТно Π»ΠΈ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ forward для интСрфСйсов?

Π”Π°, Π½ΠΎ с ΠΎΠ³ΠΎΠ²ΠΎΡ€ΠΊΠ°ΠΌΠΈ. Π˜Π½Ρ‚Π΅Ρ€Ρ„Π΅ΠΉΡΡ‹ Π² Delphi Π½Π΅ Ρ‚Ρ€Π΅Π±ΡƒΡŽΡ‚ forward-объявлСний, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ ΠΈΡ… ΠΌΠΎΠΆΠ½ΠΎ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡ‚ΡŒ Π² любом порядкС. Однако Ссли Π²Ρ‹ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚Π΅ с диспинтСрфСйсами (dispinterface) ΠΈΠ»ΠΈ ΠΊΠΎΠΌΠ±ΠΈΠ½ΠΈΡ€ΡƒΠ΅Ρ‚Π΅ интСрфСйсы с классами, ΠΌΠΎΠ³ΡƒΡ‚ Π²ΠΎΠ·Π½ΠΈΠΊΠ½ΡƒΡ‚ΡŒ ситуации, Π³Π΄Π΅ forward понадобится. ΠŸΡ€ΠΈΠΌΠ΅Ρ€:

type

IMyInterface = interface; // Forward Π½Π΅ Π½ΡƒΠΆΠ΅Π½ для ΠΎΠ±Ρ‹Ρ‡Π½Ρ‹Ρ… интСрфСйсов

TMyClass = class(TInterfacedObject, IMyInterface)

// рСализация

end;

IMyInterface = interface // ПолноС ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅

['{GUID}']

procedure DoSomething;

end;

Но Ссли интСрфСйс ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ Π² ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠΈ Π΄Ρ€ΡƒΠ³ΠΎΠ³ΠΎ интСрфСйса Π΄ΠΎ своСго ΠΏΠΎΠ»Π½ΠΎΠ³ΠΎ объявлСния, ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΠΎΡ‚Ρ€Π΅Π±ΠΎΠ²Π°Ρ‚ΡŒΡΡ forward.

Как ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΡ‚ΡŒ, экспортируСтся Π»ΠΈ функция ΠΈΠ· DLL?

Π•ΡΡ‚ΡŒ нСсколько способов:

  • πŸ”Ή Dependency Walker (depends.exe) β€” ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ всС экспортированныС Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ.
  • πŸ”Ή Команда dumpbin /exports mylib.dll (Π²Ρ…ΠΎΠ΄ΠΈΡ‚ Π² состав Visual Studio).
  • πŸ”Ή Heaventools PE Explorer β€” Π±ΠΎΠ»Π΅Π΅ ΠΏΡ€ΠΎΠ΄Π²ΠΈΠ½ΡƒΡ‚Ρ‹ΠΉ инструмСнт для Π°Π½Π°Π»ΠΈΠ·Π° DLL.

ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, Ρ‡Ρ‚ΠΎ ΠΈΠΌΠ΅Π½Π° ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ Π΄Π΅ΠΊΠΎΡ€ΠΈΡ€ΠΎΠ²Π°Π½Ρ‹ (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, _FunctionName@12 для stdcall). Π’ этом случаС Π² external Π½ΡƒΠΆΠ½ΠΎ ΡƒΠΊΠ°Π·Ρ‹Π²Π°Ρ‚ΡŒ ΠΈΠΌΠ΅Π½Π½ΠΎ Π΄Π΅ΠΊΠΎΡ€ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠ΅ имя.

ΠŸΠΎΡ‡Π΅ΠΌΡƒ ошибка появляСтся послС обновлСния Delphi?

Π­Ρ‚ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ связано с:

  • πŸ”Ή ИзмСнСниями Π² компиляторС. НовыС вСрсии Delphi ΠΌΠΎΠ³ΡƒΡ‚ строТС ΠΏΡ€ΠΎΠ²Π΅Ρ€ΡΡ‚ΡŒ forward-объявлСния.
  • πŸ”Ή ОбновлСниСм Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊ. Если Π²Ρ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚Π΅ сторонниС ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹, ΠΈΡ… Π½ΠΎΠ²Ρ‹Π΅ вСрсии ΠΌΠΎΠ³ΡƒΡ‚ Ρ‚Ρ€Π΅Π±ΠΎΠ²Π°Ρ‚ΡŒ Π΄Ρ€ΡƒΠ³ΠΈΡ… Π²Π½Π΅ΡˆΠ½ΠΈΡ… зависимостСй.
  • πŸ”Ή Настройками ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°. ПослС обновлСния ΡΠ±Ρ€ΠΎΡΡŒΡ‚Π΅ настройки компилятора (Project β†’ Options β†’ Reset to Defaults) ΠΈ настройтС Π·Π°Π½ΠΎΠ²ΠΎ.

ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡŒΡ‚Π΅ Π»ΠΎΠ³ компиляции (View β†’ Tool Windows β†’ Messages) β€” Ρ‚Π°ΠΌ ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ подсказки.

МоТно Π»ΠΈ ΠΎΡ‚Π»Π°Π΄ΠΈΡ‚ΡŒ внСшнюю DLL, Ссли Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π΅Ρ‚ ошибка с external?

Π”Π°, Π½ΠΎ для этого Π½ΡƒΠΆΠ½ΠΎ:

  1. Π£Π±Π΅Π΄ΠΈΡ‚ΡŒΡΡ, Ρ‡Ρ‚ΠΎ Ρƒ вас Π΅ΡΡ‚ΡŒ исходники DLL ΠΈΠ»ΠΈ Π΅Ρ‘ .pdb-Ρ„Π°ΠΉΠ» (для Windows).
  2. Π’ настройках ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π° (Project β†’ Options β†’ Debugger) Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ ΠΏΡƒΡ‚ΡŒ ΠΊ .pdb-Ρ„Π°ΠΉΠ»Ρƒ.
  3. Π—Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ ΠΎΡ‚Π»Π°Π΄ΠΊΡƒ Π² Delphi β€” ΠΏΡ€ΠΈ Π²Ρ‹Π·ΠΎΠ²Π΅ внСшнСй Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΎΡ‚Π»Π°Π΄Ρ‡ΠΈΠΊ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΏΠ΅Ρ€Π΅ΠΉΡ‚ΠΈ Π² Π΅Ρ‘ ΠΊΠΎΠ΄ (Ссли символичСская информация доступна).

Если исходников Π½Π΅Ρ‚, ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ дизассСмблСр (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, IDA Pro ΠΈΠ»ΠΈ Ghidra), Π½ΠΎ это Ρ‚Ρ€Π΅Π±ΡƒΠ΅Ρ‚ Π³Π»ΡƒΠ±ΠΎΠΊΠΈΡ… Π·Π½Π°Π½ΠΈΠΉ ассСмблСра.

πŸ’‘

ВсСгда провСряйтС forward-объявлСния Π½Π° ΠΏΠ°Ρ€Π½ΠΎΡΡ‚ΡŒ: Ссли объявили класс ΠΈΠ»ΠΈ ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Ρƒ с forward, ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ Π΄Π°ΠΉΡ‚Π΅ Π΅Ρ‘ ΠΏΠΎΠ»Π½ΠΎΠ΅ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ Π² Ρ‚ΠΎΠΌ ΠΆΠ΅ ΠΌΠΎΠ΄ΡƒΠ»Π΅. Π­Ρ‚ΠΎ ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ ΠΏΠΎΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΠ·Π±Π΅ΠΆΠ°Ρ‚ΡŒ 90% случаСв Π΄Π°Π½Π½ΠΎΠΉ ошибки.