Valgrind показывает утечку памяти? Возможно, это связано? - PullRequest
0 голосов
/ 10 января 2020

Я пытаюсь отладить некоторый код, который имеет утечку памяти, и запуск valgrind вызывает у меня некоторые ошибки, но у меня возникают некоторые проблемы с пониманием того, почему использование fftw вызывает проблему.

==1286== 44,384 bytes in 1 blocks are still reachable in loss record 85 of 85
==1286==    at 0x4C320A6: memalign (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==1286==    by 0x6D47864: fftwf_malloc_plain (in /usr/lib/x86_64-linux-gnu/libfftw3f.so.3.5.7)
==1286==    by 0x6D48F9E: ??? (in /usr/lib/x86_64-linux-gnu/libfftw3f.so.3.5.7)
==1286==    by 0x6D4B7D7: fftwf_solvtab_exec (in /usr/lib/x86_64-linux-gnu/libfftw3f.so.3.5.7)
==1286==    by 0x6D85B60: fftwf_rdft_conf_standard (in /usr/lib/x86_64-linux-gnu/libfftw3f.so.3.5.7)
==1286==    by 0x6E0FCE0: fftwf_configure_planner (in /usr/lib/x86_64-linux-gnu/libfftw3f.so.3.5.7)
==1286==    by 0x6E13427: fftwf_the_planner (in /usr/lib/x86_64-linux-gnu/libfftw3f.so.3.5.7)
==1286==    by 0x6E0FA6C: fftwf_mkapiplan (in /usr/lib/x86_64-linux-gnu/libfftw3f.so.3.5.7)
==1286==    by 0x6E1300A: fftwf_plan_many_dft (in /usr/lib/x86_64-linux-gnu/libfftw3f.so.3.5.7)
==1286==    by 0x6E12366: fftwf_plan_dft (in /usr/lib/x86_64-linux-gnu/libfftw3f.so.3.5.7)
==1286==    by 0x6E12065: fftwf_plan_dft_1d (in /usr/lib/x86_64-linux-gnu/libfftw3f.so.3.5.7)
==1286==    by 0x666D0C2: Framework_Fft::create_plan(FFT_SIZE) (Framework_Fft.cc:228)
==1286== LEAK SUMMARY:
==1286==    definitely lost: 0 bytes in 0 blocks
==1286==    indirectly lost: 0 bytes in 0 blocks
==1286==      possibly lost: 0 bytes in 0 blocks
==1286==    still reachable: 118,440 bytes in 1,353 blocks
==1286==         suppressed: 0 bytes in 0 blocks

HEAP SUMMARY:
==1200==     in use at exit: 118,392 bytes in 1,353 blocks
==1200==   total heap usage: 31,167,920 allocs, 31,166,567 frees, 390,943,154,294 bytes allocated
==1200== 
==1200== Searching for pointers to 1,353 not-freed blocks


Framework_fft. cc, является следующим

#include <vector>
#include <cstdio>

#include <fftw3.h>
#include <wifi_ac/Shim/Framework_Fft.h>
#include <wifi_ac/Modem/Phy/Common/Phy_Common.h>
#include <wifi_ac/Modem/Phy/Common/Trace_Macro.h>


// XXX: Update this array when adding support for new FFT sizes.
const size_t Framework_Fft::mSizeMap[FFT_COUNT] = {64, 128, 256, 512};

Framework_Fft::Framework_Fft()
{
   FFT_SIZE max_size = get_size_enum(PHY_MAX_SZFFT);

   mpInput = (fftwf_complex*)create_buffer(max_size);
   mpIntermediate = (fftwf_complex*)create_buffer(max_size);

   {
      planner::scoped_lock lock(planner::mutex());

      // These are the supported plans for FFT.
      TRACE_LEVEL_GTEQ(TRACE_VERBOSE, "INFO in " << TRACE_COUT_METHOD_NAME << ":  Creating FFT plans.");
      // JIRA TA-183: vvvvv
      switch (max_size)
      {
         // Fall-through intentional...
         case FFT_512:
            create_plan(FFT_512);
         case FFT_256:
            create_plan(FFT_256);
         case FFT_128:
            create_plan(FFT_128);
         case FFT_64:
            create_plan(FFT_64);
            break;
      }
//      create_plan(FFT_64);
//      create_plan(FFT_128);
//      create_plan(FFT_256);
//      create_plan(FFT_512);
      // JIRA TA-183: ^^^^^
      TRACE_LEVEL_GTEQ(TRACE_VERBOSE, "INFO in " << TRACE_COUT_METHOD_NAME << ":  FFT plans created.");
   }
}

Framework_Fft::~Framework_Fft()
{
   // JIRA TA-183: vvvvv
   FFT_SIZE max_size = get_size_enum(PHY_MAX_SZFFT);
   {
      planner::scoped_lock lock(planner::mutex());
      switch (max_size)
      {
         // Fall-through intentional...
         case FFT_512:
            destroy_plan(FFT_512);
         case FFT_256:
            destroy_plan(FFT_256);
         case FFT_128:
            destroy_plan(FFT_128);
         case FFT_64:
            destroy_plan(FFT_64);
            break;
      }

//      destroy_plan(FFT_64);
//      destroy_plan(FFT_128);
//      destroy_plan(FFT_256);
//      destroy_plan(FFT_512);
      // JIRA TA-183: ^^^^^
      TRACE_LEVEL_GTEQ(TRACE_VERBOSE, "INFO in " << TRACE_COUT_METHOD_NAME << ":  FFT plans destroyed.");
   }

   if (mpInput)
   {
      fftwf_free(mpInput);
      mpInput = NULL;
   }

   if (mpIntermediate)
   {
      fftwf_free(mpIntermediate);
      mpIntermediate = NULL;
   }
};

framework_complex_internal*
Framework_Fft::create_buffer(FFT_SIZE size)
{
   fftwf_complex* fftwf_buffer = NULL;
   bool error = false;
   if (size >= FFT_COUNT)
   {
      TRACE_LEVEL_GTEQ(TRACE_ERROR, "ERROR in " << TRACE_COUT_METHOD_NAME << ":  FFT_SIZE of " << size << " not supported.");
      error = true;
   }

   if (sizeof(framework_complex_internal) != sizeof(fftwf_complex))
   {
      TRACE_LEVEL_GTEQ(TRACE_ERROR, "ERROR in " << TRACE_COUT_METHOD_NAME << ":  Type framework_complex_internal size not compatible with fftwf_complex.");
      error = true;
   }

   if (!error)
   {
      fftwf_buffer =
         (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex) * mSizeMap[size]);

      if (NULL == fftwf_buffer)
      {
         TRACE_LEVEL_GTEQ(TRACE_ERROR, "ERROR in " << TRACE_COUT_METHOD_NAME << ":  Memory allocation using fftwf_malloc failed.");
         TRACE_LEVEL_GTEQ(TRACE_ERROR, "         NULL pointer is being returned.");
         error = true;
      }
   }

   if (error)
   {
      TRACE_LEVEL_GTEQ(TRACE_ERROR, "ERROR(s) occurred in " << TRACE_COUT_METHOD_NAME << ".");
//      printf("%s: Returning NULL\n", TRACE_COUT_METHOD_NAME);
   }

   return (framework_complex_internal*)fftwf_buffer;
   cout << fftwf_buffer;
}

framework_complex_internal*
Framework_Fft::create_buffer(size_t size)
{
   FFT_SIZE fft_size = get_size_enum(size);
   return create_buffer(fft_size);
}

void
Framework_Fft::free_buffer(framework_complex_internal* buffer)
{
   if (buffer)
   {
      fftwf_free(buffer);
      buffer = NULL;
   }
}

void
Framework_Fft::FftComplex(
   FFT_SIZE size,
   const framework_complex_internal* pInputBufferComplex,
   framework_complex_internal* pOutputBufferComplex)
{
   bool freeinput = false;
   framework_complex_internal* input = (framework_complex_internal*)pInputBufferComplex;
   TRACE_LEVEL_GTEQ(TRACE_VERBOSE, "INFO in " << TRACE_COUT_METHOD_NAME << ":  FftComplex of size " << (int)mSizeMap[size] << ".");
   // We may need to align the buffer that is input to fftwf.
   if ((uint64_t)pInputBufferComplex % 16 != 0)
   {
      TRACE_LEVEL_GTEQ(TRACE_INFO, "WARNING in " << TRACE_COUT_METHOD_NAME << ":  FftComplex - Input buffer does not appear to be aligned.");
      input = create_buffer(size);
      memcpy(
         input,
         pInputBufferComplex,
         sizeof(framework_complex_internal) * mSizeMap[size]);
      freeinput = true;
   }

   fftwf_execute_dft(
      mFftwfPlans[size], (fftwf_complex*)input, (fftwf_complex*)mpIntermediate);

   size_t szHalfFftSize = mSizeMap[size] / 2;

   // First half from fftwf_execute goes into 2nd half of output buffer
   memcpy(
      pOutputBufferComplex + szHalfFftSize,
      mpIntermediate,
      szHalfFftSize * sizeof(fftwf_complex));

   // Second half of fftwf_execute goes into first half of output buffer.
   memcpy(
      pOutputBufferComplex,
      mpIntermediate + szHalfFftSize,
      szHalfFftSize * sizeof(fftwf_complex));

   if (freeinput)
   {
      free_buffer(input);
   }
}

void
Framework_Fft::FftComplex(
   size_t size,
   const framework_complex_internal* pInputBufferComplex,
   framework_complex_internal* pOutputBufferComplex)
{
   FFT_SIZE fft_size = get_size_enum(size);
   FftComplex(fft_size, pInputBufferComplex, pOutputBufferComplex);
}

FFT_SIZE
Framework_Fft::get_size_enum(size_t size)
{
   FFT_SIZE fft_size = (FFT_SIZE)(FFT_COUNT - 1);
   bool size_found = false;

   for (int i = 0; i < FFT_COUNT; i++)
   {
      if (mSizeMap[i] == size)
      {
         fft_size = (FFT_SIZE)i;
         size_found = true;
         break;
      }
   }

   if (!size_found)
   {
      TRACE_LEVEL_GTEQ(TRACE_INFO, "WARNING in " << TRACE_COUT_METHOD_NAME << ":  FFT size " << size << " is invalid.");
      TRACE_LEVEL_GTEQ(TRACE_INFO, "           Performing FFT of size " << mSizeMap[fft_size] << " instead.");
   }
   return fft_size;
}

void
Framework_Fft::create_plan(FFT_SIZE fft_size)
{
   mFftwfPlans[fft_size] = fftwf_plan_dft_1d(
      mSizeMap[fft_size], mpInput, mpIntermediate, FFTW_FORWARD, FFTW_PATIENT);
}

void
Framework_Fft::destroy_plan(FFT_SIZE fft_size)
{
   if (mFftwfPlans[fft_size])
   {
      fftwf_destroy_plan(mFftwfPlans[fft_size]);
   }
}

// Added by mwk 01/10/2020 
void fftwf_cleanup(void);

Я считаю, что я создаю, уничтожаю и освобождаю по мере необходимости. У кого-нибудь есть мысли?

1 Ответ

0 голосов
/ 12 января 2020

Убедитесь, что вы используете актуальную версию Valgrind.

Возможно, проблемная переменная либо double, либо long long.

Вы можете использовать запрос gdb или client макросы для проверки инициализации отдельных адресов памяти.

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

if (SignalPower_linear_min == 0.0)
    ;
if (pBurstStateParams->PhysicalConfigParams.mFullScale_linear == 0.0)
    ;

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

...