Как решить ошибку double free
Перейти к содержимому

Как решить ошибку double free

  • автор:

Как избавиться от double free or corruption при выгрузке библиотеки?

Исходные данные
Имеется статическая библиотека назовем ее libInternal.a
Есть динамическая библиотека которая линкует libInternal.a, назовем ее libExternal.so.
Есть также исполняемый файл который динамически подгружает libExternal.so, также этот исполняемый файл линкует libInternal.a

Проблемма
Как работает исполняемый файл: загружает libExternal.so, тут же выгружает, не выполняя кода из нее, и при выходе из main() падает с сообщением double free or corruption

Если не линковать к исполняемому файлу статическую библиотеку то программа завершается корректно.
В статической библиотеке есть глобальные переменные типа std::string, если убрать их использование в статической библиотеке то программа также завершается успешно.

Примечание: я пробовал повторить ситуацию на маленьком проекте но почему-то там такой проблемы не возникло.
Из за чего может быть такая проблема? Я подозреваю что это из-за того что в памяти находятся две копии данных, но адреса то у них разные.
Для сборки проекта используется cmake-3.5.1 и g++-5.4.0

  • Вопрос задан более трёх лет назад
  • 1114 просмотров

2 комментария

Оценить 2 комментария

Ошибка: double-free

В C можно free вызвать ошибочно. В C++можно вызывать delete несколько раз. В этих примерах отображаются ошибки с delete , free а также HeapCreate .

Пример C++ — double operator delete

// example1.cpp // double-free error int main() < int *x = new int[42]; delete [] x; // . some complex body of code delete [] x; return 0; >

Чтобы создать и проверить этот пример, выполните следующие команды в командной строке разработчика Visual Studio 2019 версии 16.9 или более поздней:

cl example1.cpp /fsanitize=address /Zi devenv /debugexe example1.exe 

Результирующая ошибка — double operator delete

Screenshot of debugger displaying double-free error in example 1.

Пример «C» — double free

// example2.cpp // double-free error #include #include int main(int argc, char** argv) < char* x = (char*)malloc(10 * sizeof(char)); memset(x, 0, 10); int res = x[argc]; free(x); // . some complex body of code free(x + argc - 1); // Boom! return res; >

Чтобы создать и проверить этот пример, выполните следующие команды в командной строке разработчика Visual Studio 2019 версии 16.9 или более поздней:

cl example2.cpp /fsanitize=address /Zi devenv /debugexe example2.exe 

Результирующая ошибка — double free

Screenshot of debugger displaying double-free error in example 2.

Пример: Windows HeapCreate double HeapFree

// example3.cpp // double-free error #include #include int main()

Чтобы создать и проверить этот пример, выполните следующие команды в командной строке разработчика Visual Studio 2019 версии 16.9 или более поздней:

cl example3.cpp /fsanitize=address /Zi devenv /debugexe example3.exe 

Ошибка free(): double free detected in tcache 2

Author24 — интернет-сервис помощи студентам

Добрый день! Столкнулся с проблемой, при запуске программы появляется строка «free(): double free detected in tcache 2». Скажите, пожалуйста, в чем проблема, и как это исправить?

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
#include #include #include #include //оператор проверочного утверждения using namespace std; enum class Color // Класс перечисления для будущего цвета графика { red = 0, green, blue, }; //------------------------------------------------------------------------------ class Rhombus { private: static int AmountOfRhombus; //статическая переменная для хранения количества ромбов const int m_number;//пременная, которая содержит номер ромба.номер присваивается 1 раз и не изменяется static int lastRhombusNumber; // статическая переменная для хранения последнего номера, что бы каждый следующий имел номер на едицинцубольше double side; // строна int angle_1; // меньший угол double diagonal_1;//диагональ1 Color m_color;//цвет const string m_name;//имя ромба int* m_linksToRhombus;////указатель, в котором будет храниться адрес динамического массива ссылок, где упоминается этот ромб int m_linksAmount;//количество ромбов //------------------------------------------------------------------------------ public: // геттеры Color getColor() const {return m_color;}//геттер для цвета double getside() {return side;} // геттер для стороны int getangle_1() {return angle_1;} // геттер для угла double getdiagonal_1() {return diagonal_1;}//геттер для диагонали int getLink (int index) const {return m_linksToRhombus[index];}// возвращает по индексу страницу упомнинания //возвращает количество уравнений static int getTheAmountOfRhombus () {return AmountOfRhombus;}//возвращает количество ромбов //------------------------------------------------------------------------------------------------------------ //сеттеры void setside(int a) { assert(a!=0); side = a; } void setangle_1 (int b) { assert(b180); angle_1 = b; } void setLinkValue(int index, int value) { assert((index >= 0) && (index  m_linksAmount)); //проверка индекса m_linksToRhombus [index] = value; //присваиваем значение конкретной страницы(ссылки) элементу массива страниц (ссылок) с конкретным индексом } //------------------------------------------------------------------------------- void printInfo (bool showLink= true) const { // показываем string color; if (m_color == Color::red) color = " красного "; else if (m_color == Color::green) color = " зеленого "; else color = " синего "; cout<"Перед вами " <" № " <" цвета "<"со стороной : "<" см "<", а также "<"углами: первый и второй: "<"°, остальные: "<180-angle_1<"°, диагоналями : "*(sqrt(2+(2*cos(angle_1 * 3.14159 / 180))))<" см и "*(sqrt(2+(2*cos((180 - angle_1) * 3.14159 / 180))))<" см " ; if (showLink) { std::cout  <"Число упоминаний ромбов: "   ; for (int i = 0; i  m_linksAmount; i++) { cout  <"["   <"]: "  [i] ; } } cout  <"Общее число ромбов: "  () <"."  ; cout  <"-------------------------------------"  ; } //------------------------------------------------------------------------------------------------------------- Rhombus addRhombus(const Rhombus& RhombusToAdd) //Сложение ромбов - здесь аргумент RhombusToAdd должен быть константным,иначе константные экземпляры класса нельязя будет прибавлять { int newside = side + RhombusToAdd.side;// работает на уровне класса, а не на уровне его экземпляров double newangle_1 = angle_1; if (angle_1==RhombusToAdd.angle_1) { angle_1 = newangle_1; side = newside; std::cout  <"Ромб \"Ромб"   <"\" был изменен."  ::endl; } else { std::cout  <"Ошибка при попытке изменения ромбов \"Ромб"   <"\"."  ::endl; } std::cout  <"-------------------------------------"  ::endl; return *this; // возвращаем то, что хранится по собственному адресу (ссылку на обновленного "себя") } //------------------------------------------------------------------------------------------------------- Rhombus(double side = 0 ,double angle_1 = 0,Color color = Color::red, int linksAmount = 10) : m_color(color), m_name(" ромб "),m_linksAmount(linksAmount), m_number(++lastRhombusNumber){// констуктор setside(side); setangle_1(angle_1); assert((linksAmount >= 0) && (linksAmount  1000)); //вызываем функцию сравнения аргумента с 0 m_linksToRhombus = new int[linksAmount] {};//динамически выделяем память под массив ссылок, обнуляем его элементы AmountOfRhombus++;// увеличиваем значение переменной на 1 (количество уравнений выросло на 1) std::cout  <"Создан новый ромб."  ::endl; std::cout  <"-------------------------------------"  ::endl; } //------------------------------------------------------------------------------------------------------------- ~Rhombus() { AmountOfRhombus--; delete[] m_linksToRhombus; std::cout  <"Удален ромбов \"Ромб"   <"\"."  ::endl; std::cout  <"Общее число ромбов: "  ()  <"."  ::endl; std::cout  <"-------------------------------------"  ::endl; } }; //------------------------------------------------------------------------------------------------------------ int Rhombus:: AmountOfRhombus = 0; // Присваиваем начальные значения статическим переменным класса вне функций (по аналогии с обычными глобальными) int Rhombus:: lastRhombusNumber=0; //------------------------------------------------------------------------------------------------------------ int main() { setlocale(LC_ALL, "Russian"); const Rhombus r1 { 15,60, Color::green }; r1.printInfo(true); Rhombus r2 { 10,120, Color::red }; r2.printInfo(false); r1.~Rhombus();; Rhombus r3{ 2, 90, Color::blue, 4 }; r3.printInfo(false); Rhombus r4{ 8, 120, Color::green, 2 }; r4.printInfo(false); const Rhombus r5{ 12, 45, Color::green, 2 }; r5.printInfo(false); r2.addRhombus(r4); r2.printInfo(false); r3.addRhombus(r2); r3.printInfo(false); }

Почему возникает free(): double free detected in tcache 2? (в деструкторе)?

RabraBabr

насколько я понимаю, да, т.к. в конструктор передается аргумент с таким же именем как поле структуры. Поэтому для обращения к полю (str), а не к парметру конструктура (str) необходимо использовать this

Решения вопроса 1
«I’m here to consult you» © Dogbert

Почему возникает free(): double free detected

Потому что в этом классе не реализован конструктор копирования (а так же перемещения и операторы присваивания, но это пока не вызывает таких же ошибок). В результате при копировании объекта класса String копия получает то же значение str что и оригинал с которого она скопирована, в деструкторе копия удаляет str оригинала, а потом это же делает оригинал в своём деструкторе. См. правило трёх/пяти.

Ответ написан 13 мар. 2023
Комментировать
Нравится 4 Комментировать
Ответы на вопрос 0
Ваш ответ на вопрос

Войдите, чтобы написать ответ

программирование

  • Программирование
  • +4 ещё

C++ как сделать совместимую между компиляторами динамическую линковку функций?

  • 1 подписчик
  • 16 часов назад
  • 65 просмотров

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *