Встреча с GCC «Ошибка внутреннего компилятора: ошибка сегментации» при использовании рекурсии макросаC++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Встреча с GCC «Ошибка внутреннего компилятора: ошибка сегментации» при использовании рекурсии макроса

Сообщение Anonymous »

Этот код статического отражения C ++ может автоматически получить число и имена переменных элементов в классе агрегата, с его основным процессом, разделенным на три шага: < /p>
1.at Время компиляции, вычислить общее количество переменных членов, «постепенно пытаясь построить агрегатный класс». < /p>
. Участники, используйте структурированную привязку, чтобы разложить его на ссылки на члены, а затем получить указатель для каждого члена.#include
#include
#include
#include
#include
#include
#include

#define MS_SUB_1 0
#define MS_SUB_2 1
#define MS_SUB_3 2
#define MS_SUB_4 3
#define MS_SUB_5 4

#define MS_ADD_0 1
#define MS_ADD_1 2
#define MS_ADD_2 3
#define MS_ADD_3 4
#define MS_ADD_4 5

#define __CONNECT_MACRO(a, b) a ## b
#define CONNECT_MACRO(a, b) __CONNECT_MACRO(a, b)

#define MS_SUB(Num) CONNECT_MACRO(MS_SUB_, Num)
#define MS_ADD(Num) CONNECT_MACRO(MS_ADD_, Num)

#define MACRO_LOOP_0(CI, CE, I) CE(I)
#define MACRO_LOOP_1(CI, CE, I) CI(I) CONNECT_MACRO(MACRO_LOOP_, 0)(CI, CE, MS_ADD(I))
#define MACRO_LOOP_2(CI, CE, I) CI(I) CONNECT_MACRO(MACRO_LOOP_, 1)(CI, CE, MS_ADD(I))
#define MACRO_LOOP_3(CI, CE, I) CI(I) CONNECT_MACRO(MACRO_LOOP_, 2)(CI, CE, MS_ADD(I))

#define EMPTY_MACRO(args...)
#define MACRO_LOOP(CI, CE, Count) CONNECT_MACRO(MACRO_LOOP_, Count)(CI, CE, 0)
#define MACRO_LOOP_WITHOUT_STOP_CALLBACK(CI, Count) MACRO_LOOP(CI, EMPTY_MACRO, Count)

template
struct reflect_member_handler
{

};

template
struct reflect_of
{
private:
struct __type_placeholder
{
template
operator E() const;
};

template
consteval static std::size_t __aggregate_member_counter()
{
if constexpr( !requires{ T{ Args{}... }; } )
return sizeof...(Args) - 1;
else
return __aggregate_member_counter();
}
public:
consteval static std::size_t member_count() {
return __aggregate_member_counter();
}

inline static std::array
member_names = reflect_member_handler::get_member_names();
};

#define __SB_LIST(Num) CONNECT_MACRO(v, Num),
#define __SB_LIST_S(Num) CONNECT_MACRO(v, Num)
#define SB_LIST(Num) MACRO_LOOP(__SB_LIST, __SB_LIST_S, Num)

template
std::string_view Iget_member_name()
{
static std::source_location location = std::source_location::current();

std::string_view func_name = location.function_name();
int first = func_name.find("::", func_name.find("(&")) + 2;
int last = func_name.find(")", first);

return func_name.substr(first, last - first);
}

#define __GET_MEMBER_NAME(N) names[N] = Iget_member_name();

#define MAKE_REFLECT_MEMBER_HANDLER_1(N) \
template \
struct reflect_member_handler \
{ \
static auto get_member_names() \
{ \
static T object; \
static auto& [SB_LIST(N)] = object; \
std::array names; \
MACRO_LOOP_WITHOUT_STOP_CALLBACK(__GET_MEMBER_NAME, MS_ADD(N))\
return names; \
} \
};

#define MAKE_REFLECT_MEMBER_HANDLER_2(N) \
template \
struct reflect_member_handler \
{ \
static auto get_member_names() \
{ \
static std::byte memory[sizeof(T)]; \
static T& dummy_object = *reinterpret_cast(memory); \
static auto& [SB_LIST(N)] = dummy_object; \
std::array names; \
MACRO_LOOP_WITHOUT_STOP_CALLBACK(__GET_MEMBER_NAME, MS_ADD(N))\
return names; \
} \
};

#if 0
MAKE_REFLECT_MEMBER_HANDLER_1(0)
MAKE_REFLECT_MEMBER_HANDLER_1(1)
MAKE_REFLECT_MEMBER_HANDLER_1(2)
#else
MAKE_REFLECT_MEMBER_HANDLER_2(0)
MAKE_REFLECT_MEMBER_HANDLER_2(1)
MAKE_REFLECT_MEMBER_HANDLER_2(2)
#endif

struct test_t
{
int a;
double b;
std::string c;
};

int main()
{
for(auto it:reflect_of::member_names)
std::cout
В процессе использования рекурсии макроса я столкнулся с некоторыми странными ошибками, как показано ниже: < /p>
[main] A folder is being created: e:/cpp/reflection/build all
[build] Starting the build
[proc] Executing the command: D:\Qt\Tools\CMake_64\bin\cmake.exe --build e:/cpp/reflection/build --config Debug --target all --
[build] [1/2 50% :: 6.410] Building CXX object CMakeFiles/main2.dir/main.cpp.obj
[build] FAILED:

Код: Выделить всё

 CMakeFiles/main2.dir/main.cpp.obj
[build] d:\Qt\Tools\mingw1520_64\bin\g++.exe   -g -std=gnu++23 -Wall -Wextra -freport-bug -MD -MT CMakeFiles/main2.dir/main.cpp.obj -MF CMakeFiles\main2.dir\main.cpp.obj.d -o CMakeFiles/main2.dir/main.cpp.obj -c E:/cpp/reflection/main.cpp
[build] E:/cpp/reflection/main.cpp:76:18: warning: 'std::string_view Iget_member_name() [with auto E = (& v2)]' used but never defined
[build]    76 | std::string_view Iget_member_name()
[build]       |                  ^~~~~~~~~~~~~~~~
[build] E:/cpp/reflection/main.cpp:76:18: warning: 'std::string_view Iget_member_name() [with auto E = (& v1)]' used but never defined
[build] E:/cpp/reflection/main.cpp:76:18: warning: 'std::string_view Iget_member_name() [with auto E = (& v0)]' used but never defined
[build] during RTL pass: expand
[build] E:/cpp/reflection/main.cpp: In static member function 'static auto reflect_member_handler::get_member_names() [with T = test_t]':
[build] E:/cpp/reflection/main.cpp:87:79: internal compiler error: Segmentation fault
[build]    87 | #define __GET_MEMBER_NAME(N) names[N] = Iget_member_name();
[build]       |                                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~
[build] E:/cpp/reflection/main.cpp:30:33: note: in expansion of macro '__GET_MEMBER_NAME'
[build]    30 | #define MACRO_LOOP_3(CI, CE, I) CI(I) CONNECT_MACRO(MACRO_LOOP_, 2)(CI, CE, MS_ADD(I))
[build]       |                                 ^~
[build] E:/cpp/reflection/main.cpp:21:31: note: in expansion of macro 'MACRO_LOOP_3'
[build]    21 | #define __CONNECT_MACRO(a, b) a ## b
[build]       |                               ^
[build] E:/cpp/reflection/main.cpp:34:53: note: in expansion of macro 'MACRO_LOOP'
[build]    34 | #define MACRO_LOOP_WITHOUT_STOP_CALLBACK(CI, Count) MACRO_LOOP(CI, EMPTY_MACRO, Count)
[build]       |                                                     ^~~~~~~~~~
[build] E:/cpp/reflection/main.cpp:114:13: note: in expansion of macro 'MACRO_LOOP_WITHOUT_STOP_CALLBACK'
[build]   114 |             MACRO_LOOP_WITHOUT_STOP_CALLBACK(__GET_MEMBER_NAME, MS_ADD(N))\
[build]       |             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[build] E:/cpp/reflection/main.cpp:214:5: note: in expansion of macro 'MAKE_REFLECT_MEMBER_HANDLER_2'
[build]   214 |     MAKE_REFLECT_MEMBER_HANDLER_2(2)
[build]       |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[build] Please submit a full bug report, with preprocessed source.
[build] See  for instructions.
[build] g++.exe: fatal error: cannot execute 'D:/Qt/Tools/mingw1520_64/bin/../libexec/gcc/x86_64-w64-mingw32/15.2.0/cc1plus.exe': open temporary output file: No such file or directory
[build] compilation terminated.
[build] ninja: build stopped: subcommand failed.
[proc] command “D:\Qt\Tools\CMake_64\bin\cmake.exe --build e:/cpp/reflection/build --config Debug --target all --” Exited with code 1
[driver] Generation completed: 00:00:06.866
[build] Generation completed, exited with code 1
< /code>
После упрощения кода проекта я обнаружил, что если я расширяю контент в make_reflect_member_handler_1, компиляция может проходить нормально.  Однако, если я расширяю содержимое в make_reflect_member_handler_2, возникает эта странная ошибка.template
struct reflect_member_handler
{
static auto get_member_names()
{
static T object;
static auto& [v0] = object;
std::array names;
names[0] = __get_member_name();
return names;
}
};

template
struct reflect_member_handler
{
static auto get_member_names()
{
static T object;
static auto& [v0, v1] = object;
std::array names;
names[0] = __get_member_name();
names[1] = __get_member_name();
return names;
}
};

template
struct reflect_member_handler
{
static auto get_member_names()
{
static T object;
static auto& [v0, v1, v2] = object;
std::array names;
names[0] = __get_member_name();
names[1] = __get_member_name();
names[2] = __get_member_name();
return names;
}
}
< /code>
Код соответствующей части make_reflect_member_handler_2 после расширения макроса выглядит следующим образом: < /p>
template
struct reflect_member_handler
{
static auto get_member_names()
{
static std::byte memory[sizeof(T)];
static T& dummy_object = *reinterpret_cast(memory);
static auto& [v0] = dummy_object;
std::array names;
names[0] = __get_member_name();
return names;
}
};

template
struct reflect_member_handler
{
static auto get_member_names()
{
static std::byte memory[sizeof(T)];
static T& dummy_object = *reinterpret_cast(memory);
static auto& [v0, v1] = dummy_object; std::array names;
names[0] = __get_member_name();
names[1] = __get_member_name();
return names;
}
};

template
struct reflect_member_handler
{
static auto get_member_names()
{
static std::byte memory[sizeof(T)];
static T& dummy_object = *reinterpret_cast(memory);
static auto& [v0, v1, v2] = dummy_object;
std::array names;
names[0] = __get_member_name();
names[1] = __get_member_name();
names[2] = __get_member_name();
return names;
}
};
< /code>
Это проблема с моим кодом или компилятором? Должен ли я обновить свой компилятор или продолжать исправлять свой код? 'Iget_member_name' ", при составлении make_reflect_member_handler_1 сдается.  

Подробнее здесь: [url]https://stackoverflow.com/questions/79744358/encountering-a-gcc-internal-compiler-error-segmentation-fault-when-using-macr[/url]
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»