Другое

Исправление ошибки __builtin_operator_delete в CLion 2025.2.4

Решите ошибку «In template: call to __builtin_operator_delete selects non-usual deallocation function» в CLion 2025.2.4 с clangd. Полное руководство с рабочими решениями.

Как исправить ошибку «In template: call to ‘__builtin_operator_delete’ selects non‑usual deallocation function» в CLion 2025.2.4 с clangd?

В CLion 2025.2.4 с clangd я получаю следующую ошибку:
«In template: call to ‘__builtin_operator_delete’ selects non‑usual deallocation function»

Эта проблема возникла после обновления с CLion 2024.2 до CLion 2025.2.4. Я попытался добавить флаг -fsized-deallocation в настройки clangd, как предложено в тикете JetBrains YouTrack, но решение не сработало.

Детали окружения

  • CLion 2025.2.4 (Build #CL‑252.27397.114)
  • macOS 15.6.1 на MacBook Air с Apple M2
  • Встроенный clangd версии 21.0.0

Текущие флаги clangd

text
-Wno-unused-variable
-Wno-infinite-recursion
-Wno-array-bounds
-Wno-return-stack-address
-Werror=implicit-function-declaration
-Wshadow
-Wno-shadow-field-in-constructor-modified
-Wno-shadow-ivar
-Wuninitialized
-Wunused-label
-Wunused-lambda-capture
-fsized-deallocation

Я обнаружил, что переключение на стандартный toolchain устраняет ошибку, но при этом я не могу использовать некоторые функции libstdc++. Интересно, что CLion 2024.3.6 работает с clangd без этой проблемы.

Какое правильное решение, чтобы исправить эту ошибку в CLion 2025.2.4 и при этом продолжать использовать функции libstdc++?

Понимание ошибки

Сообщение об ошибке «In template: call to ‘__builtin_operator_delete’ selects non‑usual deallocation function» указывает на проблему с функциональностью «Sized Deallocation» в C++14. Согласно спецификации ISO C++, функции освобождения памяти с размером — это специальные перегрузки operator delete, которые принимают указатель и размер выделенной памяти.

Если перегрузка с одним аргументом не предоставлена, но существует перегрузка с размером, принимающая std::size_t в качестве второго параметра, то для обычного освобождения памяти вызывается размерная форма, и рантайм C++ передаёт размер объекта в качестве второго аргумента.

В CLion 2025.2.4 эта проблема проявляется в том, как clangd 21.0.0 обрабатывает шаблонный код, использующий sized deallocation. Ошибка возникает, потому что компилятор выбирает функцию освобождения памяти с размещением вместо обычной функции, что нарушает правила стандарта C++.

Известные решения и их ограничения

Флаг -fsized-deallocation

Как упомянуто в JetBrains YouTrack issue CPP‑29091, обычно предлагается добавить флаг -fsized-deallocation к настройкам clangd. Однако, как вы заметили, этот подход не всегда работает.

text
-fsized-deallocation

Этот флаг явно включает поддержку sized deallocation в C++14, но он может не решить специфические проблемы с шаблонами, особенно при работе с сложными иерархиями шаблонов.

Переключение цепочки инструментов

Вы обнаружили, что переключение на цепочку инструментов по умолчанию устраняет ошибку. Хотя это работает, у него есть серьёзный недостаток: вы теряете доступ к некоторым функциям libstdc++, что ограничивает возможности разработки.

Эффективные обходные решения

Комбинация флагов компилятора

Попробуйте комбинировать несколько флагов компилятора, чтобы решить проблему:

text
-fsized-deallocation -fno-sized-deallocation

Эта комбинация может заставить clangd явно обрабатывать сценарии sized deallocation корректно.

Пользовательская конфигурация компилятора

Создайте пользовательскую конфигурацию компилятора в CLion:

  1. Перейдите в Settings/PreferencesBuild, Execution, DeploymentToolchains.
  2. Выберите вашу цепочку инструментов и нажмите Edit.
  3. Добавьте следующие дополнительные флаги компилятора:
text
-fsized-deallocation -std=c++14 -faligned-allocation

Специфические исправления для шаблонов

Если проблема возникает в конкретном шаблонном коде, вы можете попробовать:

cpp
// Явно указать оператор delete в шаблонном коде
template<typename T>
void custom_delete(T* ptr) {
    if (ptr) {
        ::operator delete(ptr, sizeof(T));
    }
}

Это обходит проблему выбора шаблона, явно вызывая размерный оператор delete.

Лучшие практики для освобождения памяти в C++

Правильная реализация operator delete

Убедитесь, что ваш код следует правильным паттернам sized deallocation:

cpp
// Обычная функция освобождения памяти
void operator delete(void* ptr) noexcept;

// Функция освобождения памяти с размером
void operator delete(void* ptr, std::size_t size) noexcept;

Согласно документации cppreference, если обе перегрузки доступны, компилятор предпочтет размерную версию для обычного освобождения памяти.

Учитывание шаблонного дизайна

При проектировании шаблонов, использующих освобождение памяти:

cpp
template<typename T>
class SmartPointer {
public:
    ~SmartPointer() {
        if (ptr) {
            // Явно вызываем правильный оператор delete
            ::operator delete(ptr, sizeof(T));
        }
    }

private:
    T* ptr;
};

Управление версиями компилятора

Рассмотрите возможность закрепления версии компилятора, которая работает корректно. Поскольку CLion 2024.3.6 работал без проблем, вы можете:

  1. Использовать менеджер версий, например llvm или clang.
  2. Создать несколько цепочек инструментов с разными версиями компилятора.
  3. Переключаться между цепочками инструментов в зависимости от требований проекта.

Долгосрочные решения и перспективы

Мониторинг JetBrains YouTrack

Следите за JetBrains YouTrack issue CPP‑29091 для обновлений. JetBrains осведомлены о проблеме и могут предоставить исправление в будущих версиях CLion.

Сообщества и обходные решения

Сообщество C++ разработчиков разработало несколько обходных решений для подобных проблем. Рассмотрите возможность проверки обсуждений на Stack Overflow для проверенных сообществом решений.

Альтернативные IDE

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

Заключение

Ошибка «__builtin_operator_delete selects non‑usual deallocation function» в CLion 2025.2.4 является известной проблемой, связанной с обработкой sized deallocation в C++14. Хотя флаг -fsized-deallocation часто предлагается, он может не решить все случаи. Самые надёжные решения включают:

  1. Комбинации флагов компилятора – попробуйте сочетать -fsized-deallocation с другими связанными флагами.
  2. Пользовательские конфигурации компилятора – создайте специфические настройки цепочки инструментов с правильными флагами.
  3. Модификации шаблонного кода – явно указывайте операторы delete в проблемных шаблонах.
  4. Управление цепочками инструментов – поддерживайте несколько версий компилятора и переключайтесь при необходимости.

Для долгосрочного решения следите за обновлениями JetBrains YouTrack и рассмотрите возможность участия в обсуждении, если найдёте дополнительные решения. Похоже, проблема связана с взаимодействием clangd 21.0.0 и CLion 2025.2.4, поэтому окончательное исправление может прийти от JetBrains или команды LLVM/Clang.

Помните, что хотя обходные решения существуют, они должны рассматриваться как временные до тех пор, пока основной вопрос не будет решён в будущих обновлениях.

Источники

  1. Stack Overflow – CLion 2025.2.4: clangd: In template call to ‘__builtin_operator_delete’ selects non‑usual deallocation function
  2. JetBrains YouTrack Issue CPP‑29091 – In template: call to ‘__builtin_operator_delete’ selects non‑usual deallocation function
  3. ISO C++ Standard – N3778 – C++ Sized Deallocation
  4. CppReference – operator delete, operator delete[]
  5. Microsoft Learn – Compiler Error C2956
Авторы
Проверено модерацией
Модерация