Не удается освободить данные буфера после его перераспределения внутри рекурсивной функции. Что может быть причиной?

Итак, я столкнулся с проблемой: когда у меня есть данные, превышающие начальный размер моего буфера, и я делаю перераспределение внутри рекурсивной функции, я получаю сообщение об ошибке освобождения своего буфера.

*malloc: *** ошибка для объекта 0x100106da0: освобождаемый указатель не был выделен*

Вот код:

void recPrint(FILE *file, char *buffer, int realBufferSize, int bufferSize, char *freeCh, NodePtr* temp){

   //some code here...

    int *intArr = temp -> usedIndices;
    int i = 0;
    for(i = 0; i < 36; i++){
        if(intArr[i] == 1){
            if(i > 9){
                *freeCh = i - 10 + 'a' ;
            }else{
                *freeCh = i + '0';
            }
            realBufferSize++;
            if (realBufferSize >= bufferSize){
                buffer = realloc(buffer, (bufferSize + 100) * sizeof(char)); // <<--- REALLOC here
                bufferSize += 100;
            }
            freeCh++;
            recPrint(file, buffer, realBufferSize, bufferSize, freeCh, &temp -> children[i]);

            //now we need to remove all extra characters till the next turn
            freeCh--;
            *freeCh = '\0';
        }
    }

}

void printTrie(FILE *file, char *initialPath){

    initPath = initialPath;
    if(root.isParent == 0) return;
    char *buffer;
    char *freeCh;
    int *intArr = root.usedIndices;
    int bufferSize = 10;
    int realBufferSize = 1000;

    int i = 0;

    for(i = 0; i < 36; i++){
        buffer = calloc(1001, sizeof(char));
        freeCh = buffer;

        if(intArr[i] == 1){
            if(i > 9){
                *freeCh = i - 10 + 'a' ;
            }else{
                *freeCh = i + '0';
            }

        freeCh++;
        realBufferSize++;
        recPrint(file, buffer, realBufferSize, bufferSize, freeCh, &root.children[i]);
        free(buffer); //<<--- getting error here
        }
    }
}

person YohanRoth    schedule 17.10.2014    source источник
comment
Исходное значение указателя давно ушло после realloc. Значение указанного указателя вызывающей стороны не изменяется и становится недействительным, как только выполняется realloc (обратите внимание, что оно передается по значению по всей этой рекурсивной цепочке вызовов).   -  person WhozCraig    schedule 18.10.2014
comment
@WhozCraig вау ... какой здесь классический обходной путь?   -  person YohanRoth    schedule 18.10.2014
comment
@PutinHuylo Передайте указатель по адресу (указатель к указателю) по всей цепочке вызовов, включая отправителя, или используйте результат возврата rePrint, чтобы всегда возвращать текущее значение указателя буфера, чтобы подтолкнуть значение обратно вверх по цепочке вызовов, когда рекурсия раскручивается. Либо будет работать. Ответ Р. Саху ниже демонстрирует последний из них и определенно работает.   -  person WhozCraig    schedule 18.10.2014
comment
@WhozCraig Я пробовал оба. ни один из них на самом деле не работает для меня... поэтому, когда я пытаюсь перейти от указателя к указателю, я исправляю &buffer, и у меня есть char *buffer в качестве аргумента функции. Но тогда у меня ошибка для realloc! Там написано, что он никогда не выделялся. Что я могу здесь сделать? Возврат char тоже не работает, все та же ошибка   -  person YohanRoth    schedule 18.10.2014
comment
@WhozCraig, есть еще идеи? У меня есть индексатор (6296,0x7fff79c1f310) malloc: *** ошибка для объекта 0x100200158: неверная контрольная сумма для освобожденного объекта - объект, вероятно, был изменен после освобождения. после использования free для возвращаемого значения recPrint.   -  person YohanRoth    schedule 18.10.2014
comment
Я до сих пор не знаю, правильно ли вы это делаете, но единственное, что я хотел бы предложить, это переосмыслить математику изменения размера. мне кажется, что первоначально переданный вами размер буфера изначально на единицу меньше, чем фактический размер буфера (я полагаю, потому что вы освобождаете место для терминатора), но логика resize НЕ соответствует этому примеру. превышение вашей границы на единицу на краю приведет к повреждению вашей свободной цепи malloc, так что внимательно посмотрите там.   -  person WhozCraig    schedule 18.10.2014
comment
@WhozCraig Я пробовал как и все .. вот код, когда я возвращаю значение char * codeshare.io/W1z0w   -  person YohanRoth    schedule 18.10.2014
comment
@WhozCraig Хорошо, как выяснилось, realloc просто возвращает NULL .. в чем может быть причина? errno выдает неопознанную ошибку...   -  person YohanRoth    schedule 18.10.2014
comment
Я практически гарантирую, что вы пишете за пределами вашего распределения. Это должно быть запущено под Valgrind. Это почти гарантирует, где происходит перезапись.   -  person WhozCraig    schedule 18.10.2014


Ответы (1)


Комментарий от @WhozCraig указывает на проблему. Вот предлагаемое исправление.

  1. Вернуть буфер realloced из recPrint.

  2. Используйте free для возвращаемого значения recPrint.

char* recPrint(FILE *file, char *buffer, int realBufferSize,
               int bufferSize, char *freeCh, NodePtr* temp){

   ....

   // where you recurse...
   buffer = recPrint(file, buffer, realBufferSize, 
                     bufferSize, freeCh, &temp -> children[i]);

   // and always return the *current* buffer pointer back to the caller.
   return buffer;
}

In printTrie:

    buffer = recPrint(file, buffer, realBufferSize, bufferSize, freeCh, &root.children[i]);
    free(buffer);
person R Sahu    schedule 17.10.2014
comment
Ни один из способов не работает для меня на самом деле. Когда я возвращаю перераспределенный буфер, у меня такая же ошибка ... Возможно, это что-то, связанное с рекурсией ... Когда я перехожу от указателя к указателю, я не могу сделать realloc внутри recPrint, это дает мне аналогичную ошибку - person YohanRoth; 18.10.2014
comment
@PutinHuylo Не уверен, что вы добавили необходимый специальный соус. Рекурсивный вызов требует, чтобы вы сохранили тот потенциально измененный размер возвращаемого указателя буфера. См. дополнение к опубликованному ответу выше. - person WhozCraig; 18.10.2014
comment
Что ж, теперь у меня на том же месте следующая ошибка: indexer(6296,0x7fff79c1f310) malloc: *** ошибка для объекта 0x100200158: неверная контрольная сумма для освобождаемого объекта - вероятно, объект был изменен после освобождения. *** установить точку останова в malloc_error_break для отладки - person YohanRoth; 18.10.2014