LINUX.ORG.RU

С++ ошибка компилятора в таком виде: баг или фича?

 ,


0

1
class A
{
 public:

    int data;
    virtual void method(){} //объявлена и определена
    virtual ~A(){}
};

class B : public A
{
public:
    virtual void method(); //объявлена, но ошибочно не определена
} b;

gcc 9.3.0

Вывод компилятора

/usr/bin/ld: test.o: in function `B::B()':
test.h:19: undefined reference to `vtable for B'
/usr/bin/ld: test.o: in function `B::~B()':
test.h:19: undefined reference to `vtable for B'

То есть, при отсутствии хотя бы одной виртуальной функции класса, компилятор «ругается» на отсутствие конструктора, деструктора, но НЕ самой отсутствующей функции

★★★★★
Ответ на: комментарий от ilovewindows

забыта реализация виртуального метода

Компилятор не может знать, забыта она, или находится в другом объектнике.

Как искать забытый?

По ошибке линковщика.

то это баг, фича, вредительство мне глубоко по барабану.

Вредительством было бы писать нулевые указатели в таблицу, перенося ошибку из времени линковки в рантайм.

в MSVC

error LNK2001: неразрешенный внешний символ «public: virtual void __cdecl B::method(void)»

LNK2001

Не позорься, погугли хотя бы ошибки MSVC. «LNK****» – именно что ошибка линковки.

обхаянный всеми паскаль ткнет носом в ошибку на этапе компиляции.

Код программы, содержание ошибки и компилятор на паскале в студию.

Siborgium ★★★★★
()
Ответ на: комментарий от ilovewindows

обхаянный всеми паскаль ткнет носом в ошибку на этапе компиляции.

С паскалем не работала, поэтому спрошу, что там является единицей компиляции?

anonymous
()
Ответ на: комментарий от anonymous

Есть понятие unit, класс и реализация в одном месте, то есть нельзя объявить метод класса и где-то там, где может линкер найдет, а может нет, написать реализацию. Можно объявить abstruct метод, и не делать реализацию.

ilovewindows ★★★★★
()
Ответ на: комментарий от Siborgium

Ты зацикливаешься, сколько можно про «другой объектник». Ошибка выдана undefined reference to `vtable for B', иди ищи. LNK это именно ошибка линковки, молодец, вот тут прям молодец, , а теперь раскрой глаза «public: virtual void __cdecl B::method(void)» хобана, имя метода, которого якобы линковщик не знает. Какое «Перенося ошибку из времени линковки рантайм», читай внимательно, нереализованный метод в коде не используется.

ilovewindows ★★★★★
()
Ответ на: комментарий от ilovewindows

нельзя объявить метод класса и где-то там

А если я хочу скрыть реализацию, например в библиотеке?

anonymous
()
Ответ на: комментарий от i-rinat

Я не вижу, как ODR нарушался бы в этой ситуации. У тебя где-то метод определяется два раза?

ODR это когда должно быть не более одного раза и как минимум один раз если non-inline сущность odr-used.

[basic.def.odr]/10

Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program outside of a discarded statement; no diagnostic required.

[basic.def.odr]/7

A virtual member function is odr-used if it is not pure.

utf8nowhere ★★★
()
Ответ на: комментарий от ilovewindows

теперь раскрой глаза «public: virtual void __cdecl B::method(void)»

Клоун, почитай про decorated names в MSVC.

нереализованный метод в коде не используется.

Компилятор не знает этого. Он может использоваться в другом объектнике. Вырезанием мертвых процедур из объектников занимается линковщик.

Siborgium ★★★★★
()
Ответ на: комментарий от Siborgium

Какая строчка кода в топике нарушает эти правила?

Вариант, когда нарушает не строчка, а отсутствие строчки (строчек) ты не рассматриваешь?

utf8nowhere ★★★
()
Ответ на: комментарий от Siborgium

Когда человек начинает обзываться, начинаю подозревать что он, как бы это помягше, неправ. Это не про тебя конкретно, это так, типичное поведение. Ты просто обзываешься.:D decorated names и чо? Давай еще раз на бис про разницу компилятора и линкера, методы поиска приведенной ошибки не будет, так понял.

ilovewindows ★★★★★
()
Ответ на: комментарий от utf8nowhere

ODR это когда должно быть не более одного раза

(В таком виде, это, конечно, неверно. Можно больше одного раза в программе (в разных TU), и определения должны быть в некотором смысле идентичны. Это было написано применительно только к процитированному далее параграфу.)

utf8nowhere ★★★
()
Последнее исправление: utf8nowhere (всего исправлений: 2)
Ответ на: комментарий от anonymous

Импорт по имени, интерфейсы, структура с адресами функций

ilovewindows ★★★★★
()
Ответ на: комментарий от ilovewindows

Когда человек начинает обзываться

Я мог бы списать твое поведение на кармавхоринг, но у тебя и так пять звезд. Остается только один вариант.

decorated names и чо?

Полный текст ошибки выглядит так:

error LNK2001: неразрешенный внешний символ "DEMANGLED_NAME"(MANGLED_NAME)

Я не знаю, опустил ли @fsb4000 вторую часть, или же это новые версии MSVC ее опускают, но доступом к сырцам линковщик не обладает.

методы поиска приведенной ошибки не будет, так понял.

Еще раз, меня вообще не волнует, как вы с ТС будете это чинить. Это не ошибка, это разумное поведение для вполне конкретного и распространенного юзкейса – понимание которого, видимо, непосильно вам с ТС.

Siborgium ★★★★★
()
Последнее исправление: Siborgium (всего исправлений: 1)
Ответ на: комментарий от utf8nowhere

Нет, не рассматриваю.

Во-первых, потому что для компилятора код полностью валидный – это подтверждается как минимум тем, что три мажорных компилятора успешно компилируют этот код.

Во-вторых, стандарт говорит про программу. Никакой программы здесь нет, есть модуль трансляции.

Siborgium ★★★★★
()
Ответ на: комментарий от Siborgium

Во-первых, потому что для компилятора код полностью валидный – это подтверждается как минимум тем, что три мажорных компилятора успешно компилируют этот код.

ОП соврал про ошибку? Ок.

utf8nowhere ★★★
()
Ответ на: комментарий от utf8nowhere

Найди мне тут ошибку компилятора.

/usr/bin/ld: test.o: in function `B::B()':
test.h:19: undefined reference to `vtable for B'
/usr/bin/ld: test.o: in function `B::~B()':
test.h:19: undefined reference to `vtable for B'
Siborgium ★★★★★
()
Ответ на: комментарий от Siborgium

Ясно формулирую претензию: на сниппете ошибка ld, линковщика.

Всё ещё непонятно. Претензия в том, что на сниппете ошибка ld? Тебя разозлило, что ОП запостил ошибку линковщика?

Компилятор к ней отношения не имеет.

Или что компилятор не имеет отношения к ошибкам линковщика?

utf8nowhere ★★★
()
Ответ на: комментарий от utf8nowhere

A virtual member function is odr-used if it is not pure.

Ага, вот об этом я не знал. Хотя логично, что она используется. В vtable. С обычными функциями и невиртуальными методами это не так. Их если явно не использовать, то и наличие погоды не создаёт.

i-rinat ★★★★★
()
Ответ на: комментарий от utf8nowhere

Тебя разозлило, что ОП запостил ошибку линковщика?

ТС пишет

вывод компилятора

и приводит эти строки. ТС и @ilovewindows утверждают, что код невалидный, ты приводишь цитаты про не имеющий отношения к этой ошибке ODR и говоришь про якобы нарушение стандарта и тоже говоришь, что код невалидный, потому что при компиляции выводит ошибку.

Ошибка выводится не при компиляции, а при линковке. Современные компиляторы скармливают файлы линковщику автоматически (если не проставить соответствующий флаг), поэтому это выглядит так, будто это вывод компилятора. О том, почему этот код валидный, и почему это не ошибка компилятора, я писал выше. Единственная ошибка здесь – ТС.

Siborgium ★★★★★
()
Ответ на: комментарий от next_time

Динамическая линковка - тоже рудимент?

anonymous
()
Ответ на: комментарий от ilovewindows

исполняемый модуль собран?

Да!

z:\type 1.cpp
class A
{
 public:

    int data;
    virtual void method(){} //объявлена и определена
    virtual ~A(){}
};

class B : public A
{
public:
    virtual void method(); //объявлена, но ошибочно не определена
} b;

z:\cl.exe /c 1.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.20.27508.1 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

1.cpp

z:\dir 1.*
 Volume in drive Z has no label.
 Volume Serial Number is A29A-0A73

 Directory of z:\

17.02.2021  15:13               210 1.cpp
17.02.2021  15:13             6 241 1.obj
17.02.2021  15:06           793 152 1.pdb
               3 File(s)        799 603 bytes
               0 Dir(s)  48 292 548 608 bytes free
LamerOk ★★★★★
()
Ответ на: комментарий от i-rinat
/tmp/foo.rb:5: syntax error, unexpected local variable or method, expecting `do' or '{' or '('
    int data;
/tmp/foo.rb:13: syntax error, unexpected local variable or method, expecting `do' or '{' or '('
...лена, но ошибочно не определена
/tmp/foo.rb:14: syntax error, unexpected '}', expecting `end'
/tmp/foo.rb:14: syntax error, unexpected end-of-input, expecting `end'
theNamelessOne ★★★★★
()

у линковщика кстати есть --unresolved-symbols=ignore-in-object-files . если не ошибаюсь, как раз искомая опция, по умолчанию сказано, что это есть ошибка.

zerhud
()

Да, в gcc и clang ублюдочные сообщения. В твоём примере это не так важно, но когда ты реализуешь интерфейс из десятка-другого методов, вот это «undefined reference to vtable» вообще не помогает понять, какой метод не объявлен или не реализован.

Все защитники такого ублюдочного сообщения в этом чате объявляются преступниками против человечности.

filosofia
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.