LINUX.ORG.RU

Компиляция .so и непонятки с static членами класса

 , ,


0

2

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

Моя задача собрать его в линуксе (дебиан, g++4.9.2), итак сделал симейк, проект собирается из кучи отдельных модулей

модули собираются с ключами set(CMAKE_CXX_FLAGS "-Wall -std=c++14 -fpermissive -fPIC") в объектники add_library(NAME OBJECT ${NAME_SOURCES}) с этим все ок.

Результирующая либа собирается такой строкой

add_library(ИМЯ SHARED ${Сырцы_Главного_Модуля_Либы} $<TARGET_OBJECTS:имя_объектника1>...$<TARGET_OBJECTS:имя_объектникаN> >)

тут вроде тоже все норм (вообще первый раз в жизни сам руками собирал симейк, обычнно это IDE делали за меня).

Но а теперь то что я не могу понять до сих пор.

Есть класс, код не мой, поэтому приводить не детали реализации не могу, но тут суть именно в переменных:

	class TopologicalSorter {
	public:
		int method_1(ссылка на неконстантный контейнер);
		static const int sm_success = 0;	
		static const int sm_circle = -1;	
		static const int sm_badGraph = -2; 


	private:
		int method_1_private() //юзается в method_1

		std::vector<int> m_state;

		static const int sm_notVisited = 0;
		static const int sm_pcocessing = 1;
		static const int sm_finished = 2;
	};

итак, мы видим статик члены. Напомню в винде компиляется работает, в линуксе компиляется но не линкуется:

перемещение R_X86_64_PC32 для неопределённого символ «_ZN12_GLOBAL__N_117TopologicalSorter13sm_notVisitedE» не может использоваться при создании общего объекта(ов)

я конечно гуглил, даже на лоре чето нашел (ошибка при создании shared объекта в x86_64. (комментарий) но это не мой случай). Далее я обнаружил, что класс объявлен и реализован в .cpp файле и в пустом неймспейсе

namespace {
class TopologicalSorter {код который я урезанно привел};
}

вопрос1 - пустой неймспейс - какая-то смыслу у этого есть, или это просто автор забыл имя дать или т.п.?

далее я убрал неймспейс и получил более читаемую ошибку

undefined reference to `TopologicalSorter::sm_finished'

С которой естественно уже, помня азы плюсов - справился таким образом

	class TopologicalSorter {
	public:
		int method_1(ссылка на неконстантный контейнер); 
		static const int sm_success = 0;	
		static const int sm_circle = -1;	
		static const int sm_badGraph = -2;

	private:
		int method_1_private() //юзается из "некийМетод" в случае успеха возвра sm_success

		std::vector<int> m_state;

		static const int sm_notVisited;
		static const int sm_pcocessing;
		static const int sm_finished;
	};
        const int TopologicalSorter::sm_notVisited = 0;
        const int TopologicalSorter::sm_pcocessing = 1;
        const int TopologicalSorter::sm_finished = 2;

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

Вопрос2 - почему такие члены как sm_success или sm_badGraph успешно линкуются, а sm_notVisited, sm_pcocessing, sm_finished - нет?

Дело вероятно не в public/private (пробовал переносить в зону паблик эти три переменные, которые не линкуются). Доподленно известно что sm_notVisited, sm_pcocessing, sm_finished не используются нигде кроме класса в котором определены.

Но тем не менее: sm_badGraph и sm_circle так же используются только внутри класса, а вот sm_success имеет return наружу, но к слову и sm_badGraph, sm_circle косвенно тоже передаются наружу, через int error_code =

При этом нигде в коде-пользователе классом TopologicalSorter нет пользования этими переменными, что возвращает метод method_1, т.е. он вызывается как «процедура» в каком-то из классов-клиентов: TopologicalSorter sorter; sorter.method_1(input_output_container);

★★★★★

Последнее исправление: bonta (всего исправлений: 3)

пустой неймспейс - какая-то смыслу у этого есть

Есть, это аналог static, который ещё и с типами работает. См. «anonymous namespace».

почему такие члены как sm_success или sm_badGraph успешно линкуются, а sm_notVisited, sm_pcocessing, sm_finished - нет?

Скорее всего последние используются в каких-то выражениях, где они фигурируют как lvalue, что требует иметь адрес. По стандарту msvc тоже должен ошибку выдавать, но видимо в качестве расширения пропускает это.

xaizek ★★★★★
()

новичков с опытом работы <1 года заметно сразу, сходите перечитайте стандарт С++

anonymous
()

Кстати, JFYI, с++filt деманглит (demangle) такие имена:

$ echo _ZN12_GLOBAL__N_117TopologicalSorter13sm_notVisitedE | c++filt 
(anonymous namespace)::TopologicalSorter::sm_notVisited

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

Скорее всего последние используются в каких-то выражениях, где они фигурируют как lvalue

А они могут фигурировать не как lvalue? Лол.

anonymous
()

Вопрос2 - почему такие члены как sm_success или sm_badGraph успешно линкуются, а sm_notVisited, sm_pcocessing, sm_finished - нет?

видимо потому что аффтар мега-кода такие-же мемберы добавлял в каждый класс про работу с графами и обходом путей.

PS/ даже за намёки на Польско-Венгерско-Мелкосовт нотацию увольнять нахрен. Имя не должно носить аттрибутов видимости,типа и наследования.

MKuznetsov ★★★★★
()

4 An unnamed namespace or a namespace declared directly or indirectly within an unnamed namespace has internal linkage. All other namespaces have external linkage. A name having namespace scope that has not been given internal linkage above has the same linkage as the enclosing namespace if it is the name of

— a variable; or

— a function; or

— a named class (Clause 9), or an unnamed class defined in a typedef declaration in which the class has the typedef name for linkage purposes (7.1.3); or

— a named enumeration (7.2), or an unnamed enumeration defined in a typedef declaration in which the enumeration has the typedef name for linkage purposes (7.1.3); or

— an enumerator belonging to an enumeration with linkage; or

— a template.

ты уверен что правильно линкуешь?

xpahos ★★★★★
()

Никогда не понимал, зачем именованные целочисленные константы объявлять static const. Можно же использовать enum или constexpr.

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

constexpr внутри класса также потребует static)

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