This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Memory Manager Diagnostics doesn't work

Hi,

We are working with SDK v14.1 and are trying to debug some memory issues by enabling MEM_MANAGER_ENABLE_DIAGNOSTICS.

In memory_manager.c in function print_block_info() the macro NRF_LOG_BYTES_DEBUG is used to print the status of the memory blocks. This macro however isn't defined anywhere, seems like the log module doesn't implement it.

We tried to replace this macro by various variants of NRF_LOG_DEBUG, but it seems (also according to its definition), that this macro only allows to print strings that are defined during compile time (const). Any run time-defined strings in functions can't be printed, since their pointer becomes invalid after the function returns.

We solved the problem by changing the print_buffer array in function print_block_info() to static, to keep the pointer valid. Since the print_block_info() is called 7 times after another for all types of memory block size, print_buffer had to be changed to a two dimensional array.

This however consumes 7*80=560 bytes of RAM, essentially wasting memory, so we were wondering if there was an easier solution to this issue.

Thanks, Carl

  • Yes I tried it. It works in a sense that an outout is printed. However the output is intented for hex dump view, so only 8 bytes are printed in a line, as ascii-hex numbers. This makes it very difficult to assign the values to the table header of the memory diagnostics output.

  • Just in case anyone else comes across this issue, here's a very quick and dirty fix to the print_block_info() function:

    void print_block_info(uint32_t block_cat, uint32_t * p_mem_in_use)
    {
    #define PRINT_COLUMN_WIDTH      13
    #define PRINT_BUFFER_SIZE       80
    #define ASCII_VALUE_FOR_SPACE   32
    
    char           print_buffer[PRINT_BUFFER_SIZE];
    const uint32_t total_count   = (m_block_start[block_cat] + m_block_count[block_cat]);
    uint32_t       in_use        = 0;
    uint32_t       num_of_blocks = 0;
    uint32_t       index         = m_block_start[block_cat];
    uint32_t       column_number;
    
    // No statistic provided in case block category is not included.
    if (m_block_count[block_cat] != 0)
    {
        memset(print_buffer, ASCII_VALUE_FOR_SPACE, PRINT_BUFFER_SIZE);
    
        for (; index < total_count; index++)
        {
            if (is_block_free(index) == false)
            {
                num_of_blocks++;
                in_use += m_block_size[block_cat];
            }
        }
    
        column_number = 0;
        snprintf(&print_buffer[column_number * PRINT_COLUMN_WIDTH],
                 PRINT_COLUMN_WIDTH,
                 "| %s",
                 m_block_desc_str[block_cat]);
    
        column_number++;
        snprintf(&print_buffer[column_number * PRINT_COLUMN_WIDTH],
                 PRINT_COLUMN_WIDTH,
                 "| %d",
                 m_block_size[block_cat]);
    
        column_number++;
        snprintf(&print_buffer[column_number * PRINT_COLUMN_WIDTH],
                 PRINT_COLUMN_WIDTH,
                 "| %d",
                 m_block_count[block_cat]);
    
        column_number++;
        snprintf(&print_buffer[column_number * PRINT_COLUMN_WIDTH],
                 PRINT_COLUMN_WIDTH,
                 "| %d",
                 num_of_blocks);
    
        column_number++;
        snprintf(&print_buffer[column_number * PRINT_COLUMN_WIDTH],
                 PRINT_COLUMN_WIDTH,
                 "| %d",
                 m_min_size[block_cat]);
    
        column_number++;
        snprintf(&print_buffer[column_number * PRINT_COLUMN_WIDTH],
                 PRINT_COLUMN_WIDTH,
                 "| %d",
                 m_max_size[block_cat]);
    
        column_number++;
        const uint32_t column_end = (column_number * PRINT_COLUMN_WIDTH);
    
        for (int j = 0; j < column_end; j ++)
        {
            if (print_buffer[j] == 0)
            {
                print_buffer[j] = 0x20;
            }
        }
        snprintf(&print_buffer[column_end], 2, "|");
    
        NRF_LOG_DEBUG("%s", print_buffer);
    
        (*p_mem_in_use) += in_use;
    }
    }
    
  • Dear Sigurd,

    I am working with SDK 15.2.0. When MEM_MANAGER_ENABLE_DIAGNOSTICS is enabled, build would be failed because of undefined reference to NRF_LOG_BYTES_DEBUG.

    What should I do for tracing memory allocation?

    Thanks,

    Jianxuan

  • Hi Jianxuan,

    You could try to replace NRF_LOG_BYTES_DEBUG with NRF_LOG_INFO_ARRAY, where you implement NRF_LOG_INFO_ARRAY as:

    void NRF_LOG_INFO_ARRAY(uint8_t * array, uint8_t array_size)
    {
        for(int i = 0; i < array_size; i++)
        {
            NRF_LOG_RAW_INFO("0x%x ",array[i]);
        }
        NRF_LOG_RAW_INFO("\r\n");
    }

    You could also test Daniel Sullivan's solution (see the code he posted).

    And you could also try NRF_LOG_HEXDUMP_INFO().

Related