У меня есть простой код с функцией fftw, который иногда работает нормально, а иногда возвращает Segmentation fault, поэтому я запустил Valgrind с кодом и вот что я получил:
static const int nx = 128;
static const int ny = 128;
static const int nz = 128;
static const int ncomp = 2;
using namespace std;
void r2c3D(double rArr[], double cArr[][ncomp]);
int main(){
double *f;
f = (double*) fftw_malloc((nx*ny*nz) *sizeof(double));
memset(f, 42, (nx*ny*nz) * sizeof(double));
fftw_complex *fk;
fk = (fftw_complex*) fftw_malloc((nx*ny*nz) * sizeof(fftw_complex));
memset(fk, 42, (nx*ny*nz)* sizeof(fftw_complex));
r2c3D(f,fk);
free(f);
free(fk);
}
void r2c3D(double rArr[], double cArr[][ncomp]){
fftw_complex *input_array;
input_array = (fftw_complex*) fftw_malloc((nx*ny*nz)*sizeof(fftw_complex));
memcpy(input_array, rArr, (nx*ny*nz) * sizeof(fftw_complex));
fftw_plan forward = fftw_plan_dft_3d(nx, ny, nz, input_array, cArr, FFTW_FORWARD, FFTW_ESTIMATE);
fftw_execute(forward);
fftw_destroy_plan(forward);
fftw_cleanup();
fftw_free(input_array);
}
И сообщение Valgrind, которое я получаю:
==265== Invalid read of size 8
==265== at 0x485294F: memmove (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==265== by 0x10938B: memcpy (string_fortified.h:29)
==265== by 0x10938B: r2c3D(double*, double (*) [2]) (MemoryLeakTest.cpp:74)
==265== by 0x10920B: main (string_fortified.h:59)
==265== Address 0x63d9098 is 16,777,240 bytes inside a block of size 16,777,248 in arena "client"
который указывает на эту строку в моей функции:
memcpy(input_array, rArr, (nx*ny*nz) * sizeof(fftw_complex));
Я все еще не понимаю, в чем проблема с кодом выше! Я всю ночь ломал себе голову над этим, я не уверен, почему это происходит, я что-то упустил ?? Спасибо!
@PaulSanders строка 74 memcpy(input_array, rArr, (nx*ny*nz) * sizeof(fftw_complex));
Язык C++ говорит, что первые 32 символа в символе должны быть уникальными. Вы можете иметь больше (в зависимости от ограничений компилятора). Так что используйте их. Я рекомендую вам изменить название вашей функции на r2d2, но это мое мнение.
Откройте свой любимый справочник по C++ и почитайте: std::vector, new, delete. Функция malloc осталась над материалом C и не вызывает конструкторы.
@ThomasMatthews Обычно да, но для FFTW рекомендуется fftw_malloc.
Похоже, r2c3d следует объявить как: void r2c3D(double rArr[], fftw_complex *cArr) - Я удивлен, что ваш код вообще компилируется. Кроме того, вы передаете переменные двух разных типов в memcpy, зачем вы это делаете?
Это memset не делает того, что вы думаете. Он не устанавливает каждое значение double равным 42.
Мне кажется, что это простой код C с единственной плохой строкой C++: с использованием пространства имен std
@PaulSanders Я использую 3D-комплекс для сложного плана FFTW, поэтому memcpy копирует реальные входные данные в «фиктивный» комплексный массив fftw для передачи
В этом случае скопируйте свои элементы в цикле. memcpy не подходит для этой работы.





rArr — это (nx*ny*nz) *sizeof(double), а input_array — это (nx*ny*nz)*sizeof(fftw_complex), fftw_complex — это два двойника.
Вы выделили f как
f = (double*) fftw_malloc((nx*ny*nz) *sizeof(double));
но читая это как
memcpy(input_array, rArr, (nx*ny*nz) * sizeof(fftw_complex));
если sizeof(fftw_complex) отличается от double, вы получите ошибку
Но вы можете выделить реальные массивы как (double *) fftw_malloc(sizeof(double) * n) из: fftw.org/fftw3_doc/Memory-Allocation.html
@ Джейми Нет, не переносным способом. Я имею в виду, что это может работать, но обычно компилятор C/C++ может вставлять отступы, например, sizeof(fftw_complex) > 2*sizeof(double). Это довольно общее правило — если вы не укажете элементы структуры, которые должны быть упакованы вместе (через __attribute__(packed) или #pragma pack), sizeof(some struct) >= sum of sizeof(member)
И мое. Какая строка является строкой 74, пожалуйста? Кроме того, это не ваша непосредственная проблема, а ваши вызовы
freeв основном должны бытьfftw_free.