Я испытываю очень странную ошибку в своем коде. Я должен выделить некоторые необработанные буферы для взаимодействия с библиотекой C.
Я делаю это следующим образом, где T является параметром шаблона для фактически используемого типа, в основном double или int:
char * buffer = new char[size * sizeof(T)];
В большинстве случаев это работает, но, по крайней мере, на одной машине в не вполне понятных условиях, память, похоже, повреждена. Программа не сбой, но базовый численный алгоритм приводит к несколько иным и неправильным результатам. По крайней мере, я мог отследить проблему до данной строки выше и найти исправление (которое я действительно не понимаю):
char * buffer = new char[size * sizeof(T) + 1];
При этом ошибка больше не может быть воспроизведена, и программа работает нормально.
Но на данный момент я понятия не имею, что делать дальше.
Программа запускается демоном MPI, поэтому я имею ограниченную возможность использовать программы анализа.
Попробуйте скомпилировать программу с помощью AddressSanitizer. Вы будете получать ошибку каждый раз, когда что-то пишет за выделенным буфером.
Похоже, что у вас повреждение памяти кучи. Это может принимать разные формы. Это может быть так же просто, как переполнение буфера из-за ошибки "один за другим", и дополнительное выделение защищает вас от этого. Но это может быть почти любая ошибка памяти, например, блуждающая запись через недопустимый указатель, использование после бесплатного, двойного доступа и т.д. Ошибка может быть в вашем коде или может быть в библиотеке C. Это также может быть непонимание API, который вы используете.
Убедитесь, что вы проверяете документацию API, чтобы полностью понять требования к размеру, право собственности (кто несет ответственность за освобождение памяти) и срок службы этих буферов (когда это безопасно для их освобождения).
Существует множество инструментов, помогающих найти такие ошибки памяти. Valgrind, Address Sanitizer, AppVerifier, отладочные версии реализации malloc/free и функции new/delete и т.д.
Помните, что вам не нужно использовать новый/удалить себя. Вы можете использовать std::vector
для создания буфера и передать указатель на первый элемент в C API. Это может помочь избежать множества распространенных ошибок, например, неправильно вычислить необходимый размер, забыть освободить память, сделать двойной доступ и т.д.