Выделение / повреждение исходного буфера - как продолжить отладку?

0

Я испытываю очень странную ошибку в своем коде. Я должен выделить некоторые необработанные буферы для взаимодействия с библиотекой C.

Я делаю это следующим образом, где T является параметром шаблона для фактически используемого типа, в основном double или int:

char * buffer = new char[size * sizeof(T)];

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

char * buffer = new char[size * sizeof(T) + 1];

При этом ошибка больше не может быть воспроизведена, и программа работает нормально.

Но на данный момент я понятия не имею, что делать дальше.

  • Что может быть проблемой, когда это помогает + 1?
  • Что мне следует исследовать дальше?

Программа запускается демоном MPI, поэтому я имею ограниченную возможность использовать программы анализа.

  • 0
    Может показаться, что буфер переполняется, возможно, постоянно, но разные параметры компилятора и то, находитесь ли вы в режиме отладки или выпуска, могут показаться, что проблем нет. Если вы можете запустить код под Valgrind, он, вероятно, поймет, где это происходит, в противном случае вам просто нужно будет отследить его вручную.
  • 0
    Это сильно зависит от того, что вы делаете с этим буфером.
Показать ещё 1 комментарий
Теги:
debugging
memory
heap
dynamic-memory-allocation

2 ответа

2

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

1

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

Убедитесь, что вы проверяете документацию API, чтобы полностью понять требования к размеру, право собственности (кто несет ответственность за освобождение памяти) и срок службы этих буферов (когда это безопасно для их освобождения).

Существует множество инструментов, помогающих найти такие ошибки памяти. Valgrind, Address Sanitizer, AppVerifier, отладочные версии реализации malloc/free и функции new/delete и т.д.

Помните, что вам не нужно использовать новый/удалить себя. Вы можете использовать std::vector для создания буфера и передать указатель на первый элемент в C API. Это может помочь избежать множества распространенных ошибок, например, неправильно вычислить необходимый размер, забыть освободить память, сделать двойной доступ и т.д.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню