проблема с контейнерами: *** glibc обнаружен *** free (): неверный указатель: 0x41e0ce94 *** - PullRequest
1 голос
/ 15 апреля 2009

У меня есть программа C ++ в Linux, которая через некоторое время вылетает с сообщением:

*** glibc detected *** free(): invalid pointer: 0x41e0ce94 ***

Внутри программы я широко использую контейнеры. Они должны хранить объекты простого класса.

РЕДАКТИРОВАТЬ 2009-4-17:

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

Ответы [ 5 ]

4 голосов
/ 15 апреля 2009

Попробуйте использовать std :: string для хранения строкового значения вместо необработанного указателя на символ. Тогда вам не придется беспокоиться об управлении строковыми данными в ваших методах назначения, копирования и уничтожения. Скорее всего, ваша проблема лежит там.

Edit: нет проблем с новым классом, который вы опубликовали, и нет проблем с первой версией, если вы используете только char * для указания на строковые константы. Проблема заключается в другом месте программы или в том, как вы используете класс. Вам придется тратить больше времени на копание в отладчике и / или valgrind, чтобы отследить проблему. Я бы выяснил, на что указывает указанный адрес, и попытался бы определить, почему он освобождается дважды.

3 голосов
/ 15 апреля 2009

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

Редактировать: Только что заметил, что у вас нет оператора присваивания - при условии, что ваш конструктор и деструктор копирования в порядке, вам также нужен оператор присваивания, как std :; контейнеры будут использовать его.

1 голос
/ 15 апреля 2009

Это, безусловно, неверное строковое значение. Использование std :: string может помочь в этом отношении, если это проблема с висящими указателями. Также убедитесь, что все инициализации строки работают как положено.

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

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

В C ++ возможно определить функцию, которая должна возвращать строку, но ничего не возвращает, и вы получите плохую строку (как правило, компилятор поймает «Достигнутый конец не-void функции») , но не всегда).

То же самое касается использования valgrind.

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

РЕДАКТИРОВАТЬ 4-16

В этот момент я бы проверил, что значения объекта правильно сформированы при конструировании / разрушении. (попробуйте распечатать их?) Если все выглядит хорошо, вам, возможно, придется поискать ошибку в другом месте кода.

1 голос
/ 15 апреля 2009

Я боролся с C / C ++-приложением, которое мы разрабатываем, и первые идеи, которые приходят мне в голову,

  • Указатель был изменен, и он указывает на недопустимое значение (ptr ++;) или что-то в этом роде.
  • Вы освободили объект, но указатель все еще держит направление.

    Инструмент типа Valgrind может помочь вам обнаружить возможные ошибки в коде. Для установки:

    sudo apt-get install valgrind

    И использовать его:

    valgrind --tool = memcheck --leak-check = full ...

    Он будет сообщать об ошибках во время работы программы, а также будет сообщать вам о ее завершении. Единственная проблема заключается в том, что Valgrind определяет в качестве возможной проблемы, не может быть реальной проблемой. Но это отправная точка.

0 голосов
/ 15 апреля 2009

Что внутри твоего деструктора? Вероятно, это освобождает от cstring. И если это так, то вы разделяете указатель cstring на экземпляры, и каждый экземпляр освобождает один и тот же указатель.

...