Простая реализация C для отслеживания памяти malloc/free?

ОБНОВЛЕНИЕ 2: Это будет наилучший подход

Попробуйте его

WITH Numbers AS
(SELECT TOP(@X.value('count(//ID)','int')) ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS Nmbr FROM master..spt_values)   
SELECT Nmbr 
      ,@X.value('(//ID[sql:column("Nmbr")])[1]','int') AS ID
      ,@X.value('(//AppCode[sql:column("Nmbr")])[1]','nvarchar(max)') AS AppCode
      ,@X.value('(//SomeMore[sql:column("Nmbr")])[1]','nvarchar(max)') AS SomeMore
FROM Numbers;

Идея

  • подсчитать идентификаторы и вернуть производное [117 ] таблица с порядковым номером (в данном случае 1,2,3,4,5). Затем используйте этот номер для адресации элементов по их положению.

Еще два подхода, просто для удовольствия: -)

Это должно работать со многими столбцами довольно быстро:

DECLARE @X XML = '<ROOT>
                      <RECORD>
                          <ID>1</ID>
                          <AppCode>Code 1</AppCode>
                          <ID>2</ID>
                          <AppCode>Code 2</AppCode>
                          <ID>3</ID>
                          <AppCode>Code 3</AppCode>
                          <ID>4</ID>
                          <AppCode>Code 4</AppCode>
                          <ID>5</ID>
                          <AppCode>Code 5</AppCode>
                      </RECORD>
                  </ROOT>';
WITH allIDs AS
(
    SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS Pos
          ,id.value('text()[1]','int') AS ID
    FROM @X.nodes('/ROOT/RECORD/ID') A(id)
)
SELECT ai.Pos
      ,ai.ID
      ,@X.value('/ROOT[1]/RECORD[1]/AppCode[sql:column("ai.Pos")][1]','nvarchar(max)') AS AppCode
      ,@X.value('/ROOT[1]/RECORD[1]/SomeMore[sql:column("ai.Pos")][1]','nvarchar(max)') AS SomeMore
FROM allIDs ai
ORDER BY ai.Pos;

Идея:

[ 1130]
  • Считать идентификаторы и найти их положение
  • Считать соответствующие элементы, используя позицию идентификатора, через sql:column()
    • ОБНОВЛЕНИЕ: Еще один подход с использованием условно агрегация

      Это должно быть быстрее:

      WITH AllNodes AS
      (
          SELECT (ROW_NUMBER() OVER(ORDER BY (SELECT NULL))-1) / 3 AS RowGroup
                ,nd.value('local-name(.)','nvarchar(max)') AS NodeName
                ,nd.value('text()[1]','nvarchar(max)') AS NodeValue
          FROM @X.nodes('/ROOT/RECORD/*') A(nd)
      )
      SELECT RowGroup
            ,MAX(CASE WHEN NodeName='ID' THEN NodeValue END) AS ID
            ,MAX(CASE WHEN NodeName='AppCode' THEN NodeValue END) AS AppCode
            ,MAX(CASE WHEN NodeName='SomeMore' THEN NodeValue END) AS SomeMore
      FROm AllNodes
      GROUP BY RowGroup
      

      Идея

      • Мы читаем все узлы как EAV-структуру. (ROW_NUMBER-1)/3 (целочисленное деление!) Вернет групповой индекс, который мы можем использовать в GROUP BY. Остальное - старомодный PIVOT .

      Предупреждения для обоих подходов :

      • Для этого требуется структура без отсутствующих элементов. Если XML может включать разделы, в которых отсутствует один из узлов-последователей , это не сработает.
      • Решение с ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) сработало для меня во всех случаях, когда я его использовал. Но стоит отметить, что это не гарантирует возвращение правильной позиции.
      • [Тысяча сто тридцать два]
    11
    задан dubnde 12 May 2009 в 16:48
    поделиться

    6 ответов

    Вы можете выделить несколько дополнительных байтов в свою оболочку и поместить либо идентификатор (если вы хотите связать malloc () и free ()) или просто размер. Просто malloc (), что намного больше памяти, сохраните информацию в начале вашего блока памяти и переместите указатель, который вы возвращаете, на это много байтов вперед.

    Это, кстати, также легко можно использовать для указателей / отпечатков пальцев и тому подобное.

    13
    ответ дан 3 December 2019 в 07:39
    поделиться

    Либо вы можете получить доступ к внутренним таблицам, используемым ] malloc / free (см. этот вопрос: Где malloc () / free () хранить выделенные размеры и адреса? для некоторых подсказок), или вам нужно управлять своими собственные таблицы в ваших оболочках.

    2
    ответ дан 3 December 2019 в 07:39
    поделиться

    Вы всегда можете использовать valgrind вместо катания собственной реализации. Если вам не важен объем выделяемой памяти, вы можете использовать еще более простую реализацию: (Я сделал это очень быстро, поэтому могли возникнуть ошибки, и я понимаю, что это не самая эффективная реализация. PAllocedStorage следует дать начальный размер и увеличение на некоторый коэффициент для изменения размера и т. д., но вы поняли идею.)

    РЕДАКТИРОВАТЬ: Я пропустил, что это было для ARM, насколько мне известно, valgrind недоступен для ARM, так что это может быть вариант.

    static size_t indexAllocedStorage = 0;
    static size_t *pAllocedStorage = NULL;
    static unsigned int free_calls = 0; 
    static unsigned long long int total_mem_alloced = 0; 
    
    void * 
    my_malloc(size_t size){
        size_t *temp;
        void *p = malloc(size);
        if(p == NULL){
        fprintf(stderr,"my_malloc malloc failed, %s", strerror(errno));
        exit(EXIT_FAILURE);
        }
    
        total_mem_alloced += size;
    
        temp = (size_t *)realloc(pAllocedStorage, (indexAllocedStorage+1) * sizeof(size_t));
        if(temp == NULL){
            fprintf(stderr,"my_malloc realloc failed, %s", strerror(errno));
             exit(EXIT_FAILURE);
        }
    
        pAllocedStorage = temp; 
        pAllocedStorage[indexAllocedStorage++] = (size_t)p;
    
        return p;
    }
    
    void 
    my_free(void *p){
        size_t i;
        int found = 0;
    
        for(i = 0; i < indexAllocedStorage; i++){
        if(pAllocedStorage[i] == (size_t)p){
            pAllocedStorage[i] = (size_t)NULL;
            found = 1;
            break;
            }
        }
    
        if(!found){
            printf("Free Called on unknown\n");
        }
    
        free_calls++;
        free(p);
    }
    
    void 
    free_check(void) {
        size_t i;
    
        printf("checking freed memeory\n");
        for(i = 0; i < indexAllocedStorage; i++){   
            if(pAllocedStorage[i] != (size_t)NULL){
                printf( "Memory leak %X\n", (unsigned int)pAllocedStorage[i]);
                free((void *)pAllocedStorage[i]);
            }
        }
    
        free(pAllocedStorage);
        pAllocedStorage = NULL;
    }
    
    1
    ответ дан 3 December 2019 в 07:39
    поделиться

    Я бы использовал rmalloc . Это простая библиотека (на самом деле это всего два файла) для отладки использования памяти, но она также поддерживает статистику. Поскольку вы уже используете функции оболочки, для нее должно быть очень легко использовать rmalloc. Имейте в виду, что вам также необходимо заменить strdup и т. Д.

    0
    ответ дан 3 December 2019 в 07:39
    поделиться

    Вашей программе может также потребоваться перехватить realloc (), calloc (), getcwd () (поскольку в некоторых реализациях она может выделять память, когда буфер равен NULL) и, возможно, strdup () или аналогичный функция, если она поддерживается вашим компилятором

    0
    ответ дан 3 December 2019 в 07:39
    поделиться

    Если вы работаете на x86 , вы можете просто запустить свой двоичный файл под valgrind , и он будет собирать всю эту информацию для вас, используя стандартная реализация malloc и free . Простой.

    0
    ответ дан 3 December 2019 в 07:39
    поделиться
    Другие вопросы по тегам:

    Похожие вопросы: