2013-02-14 2 views
1

Исправлено: Проблема была с рекурсией, а не указателями. Когда он вернется через каждую рекурсию, он вернет возвращаемый VAR к старой maintree. Исправлено, создав глобальный VAR и установив его перед возвратом, а затем выполнил полную функцию return void. Нет утечек памяти.Возврат адреса указателя из функции в C

Я пытаюсь передать адрес указателя malloc'd в переменную-указатель в main().

Код работает до определенной точки. Вместо того, чтобы передавать адрес указателя из FinalTree на главную, он создает новую копию, что означает, что я не могу освободить() память, которая была malloc'd в FinalTree(). Когда я делаю проверку памяти, я остаюсь с некоторой свободной памятью.

Вот код до сих пор:

Tree* FinalTree(Forest** forest, int FinalFreq) 
{ 

    Tree* maintree = mktree(); //this function calls malloc and have to use it 
    Tree* tree1 = pick(*forest); 
    Tree* tree2 = pick(*forest); 

    maintree->frequency = tree1->frequency + tree2->frequency; 
    maintree->left = tree1; 
    maintree->right = tree2; 

    //Make sure forest isnt barren 
    if (maintree->frequency != FinalFreq) 
    { 
     plant(*forest, maintree); 
     FinalTree(forest, FinalFreq); 
    } 

    return maintree; 
} 

Это вызывается из основной() путем:

Tree* tfinal = FinalTree(&finit, header.checksum); 

Указатели вождения меня с ума .. Что мне не хватает?

+0

Что делает «завод»? – junix

+0

В основном это просто добавляет узел обратно в список. Проект состоит в том, чтобы «распаковать» файл, созданный деревом Хаффмана. Это просто восстановление дерева из сжатого файла. Свободная функция для леса очищает ВСЕ узлы в лесу. Valgrind говорит, что только 1 блок не освобождается, и я проследил его до возвращаемого maintree var. – Dyonovan

+1

Я не совсем уверен, что я следую. Мне кажется, что проблема заключается в рекурсивном вызове 'FinalTree', чей адрес возврата, который вы нигде не сохраняете, и, следовательно, не может' free() ', это правильно? –

ответ

0

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

Эта функция создает дерево, но возвращает только адрес корневого узла верхнего уровня. Ваша проблема в том, что если вы free(), что один, остальная часть дерева по-прежнему выделена, правильно? Если это так, я думаю, что решение этого заключается в том, чтобы написать выделенную функцию FreeTree(Tree *), которая пересекает дерево, и отдельные узлы листьев на пути назад.

Нечто подобное (не проверено):

void FreeTree(Tree *tree) { 
    if (tree == NULL) 
    return; 

    FreeTree(tree->left); 
    FreeTree(tree->right); 
    free(tree);                            
} 

Update: Ах хорошо. Это действительно странно. Я не вижу ничего в функции, которая изменила бы maintree в стороне от mktree(), который ее создает. Если plant не принимает ссылку на указатель:

void plant(Forest forest, Tree *&tree) 

Затем plant() может изменить указатель maintree указывает. В противном случае похоже, что он должен возвращать корневой узел.

+0

Я думаю, я не объясняю это правильно. У меня уже есть функция, которая будет освобождать() верхний узел и ВСЕ узлы внизу. (Это было фактически уже предоставлено нам. Что, по-видимому, связано с тем, что tFinal в main() не указывает на кусок, который был malloc'd для maintree. – Dyonovan

+0

Прото для растения - bool plant (Forest * f, Tree * t); – Dyonovan

+0

Да, если честно, я в недоумении. Указатель, возвращенный вызовом main на 'FinalTree()', должен действительно вернуть указатель корневого узла, мне кажется. Передача этого указателя на выделенную функцию выделения дерева должна правильно ли удалить все дерево.Есть ли вероятность, что в этой функции есть больше кода, чем вы вставили в эту функцию? Также не могли бы вы рассказать о том, как вы сталкиваетесь с проблемой, с точки зрения перспективы? (то есть в основном, код, который вы используйте для вызова 'FinalTree()', а также ваш код, чтобы освободить его, и как вы заключаете, что это копия, а не оригинал) –

Смежные вопросы