Valgrind: почему я получаю ошибку сегментации с memcpy

У меня есть простой код с функцией 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));

Я все еще не понимаю, в чем проблема с кодом выше! Я всю ночь ломал себе голову над этим, я не уверен, почему это происходит, я что-то упустил ?? Спасибо!

И мое. Какая строка является строкой 74, пожалуйста? Кроме того, это не ваша непосредственная проблема, а ваши вызовы free в основном должны быть fftw_free.

Paul Sanders 11.08.2023 18:56

@PaulSanders строка 74 memcpy(input_array, rArr, (nx*ny*nz) * sizeof(fftw_complex));

Jamie 11.08.2023 18:57

Язык C++ говорит, что первые 32 символа в символе должны быть уникальными. Вы можете иметь больше (в зависимости от ограничений компилятора). Так что используйте их. Я рекомендую вам изменить название вашей функции на r2d2, но это мое мнение.

Thomas Matthews 11.08.2023 18:59

Откройте свой любимый справочник по C++ и почитайте: std::vector, new, delete. Функция malloc осталась над материалом C и не вызывает конструкторы.

Thomas Matthews 11.08.2023 19:01

@ThomasMatthews Обычно да, но для FFTW рекомендуется fftw_malloc.

Paul Sanders 11.08.2023 19:13

Похоже, r2c3d следует объявить как: void r2c3D(double rArr[], fftw_complex *cArr) - Я удивлен, что ваш код вообще компилируется. Кроме того, вы передаете переменные двух разных типов в memcpy, зачем вы это делаете?

Paul Sanders 11.08.2023 19:17

Это memset не делает того, что вы думаете. Он не устанавливает каждое значение double равным 42.

Sam Varshavchik 11.08.2023 19:37

Мне кажется, что это простой код C с единственной плохой строкой C++: с использованием пространства имен std

prapin 11.08.2023 20:22

@PaulSanders Я использую 3D-комплекс для сложного плана FFTW, поэтому memcpy копирует реальные входные данные в «фиктивный» комплексный массив fftw для передачи

Jamie 11.08.2023 20:31

В этом случае скопируйте свои элементы в цикле. memcpy не подходит для этой работы.

Paul Sanders 11.08.2023 21:37
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
10
50
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

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

Jamie 11.08.2023 19:03

@ Джейми Нет, не переносным способом. Я имею в виду, что это может работать, но обычно компилятор C/C++ может вставлять отступы, например, sizeof(fftw_complex) > 2*sizeof(double). Это довольно общее правило — если вы не укажете элементы структуры, которые должны быть упакованы вместе (через __attribute__(packed) или #pragma pack), sizeof(some struct) >= sum of sizeof(member)

Severin Pappadeux 11.08.2023 19:57

Другие вопросы по теме