#c #pointers #c99
#c #указатели #c99
Вопрос:
Я пытаюсь устранить утечки памяти и нашел один источник. Я использую malloc’in в указателе в одной функции и освобождаю его в другой, но мне не хватает понимания того, как скопировать значение, на которое указывает указатель, и при этом иметь возможность освободить указатель.
Current implementation (with memory leak):
// This code has been greatly simplified
// and as such does not appear to have any purpose
int foo(){
int bestval = 0;
char *best;
char *match;
for (int i=0;i<3;i ) {
int returnValue = bar(amp;best);
if (returnValue > 10) {
(1)
match = best;
}
}
printf("%s", match);
(2)
return 0;
}
int bar(char ** best) {
char*s = "Hello!";
*best = malloc(strlen(s) 1);
strcpy(*best,s);
return 0;
}
Два вопроса
-
Если бы мне пришлось освобождать память в (1), а не в (2), как бы я это сделал, чтобы в match все еще было то, что содержалось в best?
-
Должен ли я выполнять strcpy, чтобы копировать наилучшим образом, чтобы соответствовать? Если да, должен ли я выполнить другой malloc в foo?
Комментарии:
1. Предполагая, что в точке два есть свободное значение, опубликованный вами код не протекает, однако после ‘2’ совпадение также недопустимо после этой точки… Вы запускаете этот код в цикле?
2. Зачем вам нужны 2 указателя
best
иmatch
? Вы можете просто использоватьbest
иfree
это в (2).3. @forsvarir, да, я запускаю его в цикле, именно поэтому я рассматриваю возможность реализации free в (1).
4. Является ли цикл внутри Foo или внешним по отношению к нему? Если это есть в нем, это, вероятно, имеет отношение к вашей утечке памяти … можете ли вы указать, где начинается / заканчивается цикл в вашем фрагменте кода
5. Цикл вокруг bar() — я подозреваю, что вы можете быть правы — мое общее ощущение таково, что в каждом из циклов я выполняю malloc и у меня нет подходящей возможности освободить его. Мы были бы весьма признательны за некоторое направление.
Ответ №1:
Небольшая попытка в темноте, предполагая, что в Foo есть цикл…
int foo()
{
int bestval = 0;
char *best;
char *match = 0; // initialize to null
// start some loop
for (int i=0;i<3;i ) {
// fetch the next best value...
int returnValue = bar(amp;best);
// some check (if best is really best!)
if (returnValue > 10) {
// if match has previously been populated, free it
if(match) {
free(match);
}
// save the new best value
match = best;
}
else {
// not saving best in match, so free it!
free(best);
}
}
// end some loop
// only do this if match was successful?!?
if(match) {
printf("%s", match);
// clean up once the best of the best has been used...
free(match);
}
return 0;
}
Комментарии:
1. Мне это нравится, и в этом есть смысл. Я попробую это и сообщу вам о своих результатах!
2. @Rio: Я только что добавил еще один свободный… если вы не сохраняете best в match, вам нужно убедиться, что вы его освободили…
3. Последнее было решающим!
4. Как освободить автоматическую переменную в стеке (например,
match
andbest
)?!!
Ответ №2:
На панели функций strcpy должен выглядеть как
strcpy(*best,s);
В основной функции вы можете скопировать значение, на которое лучше всего указывает, с помощью
strcpy(match, best);
free(best);
совпадение должно указывать на допустимый блок памяти раньше. Если вы выполните
match = best;
free(best);
совпадение также будет недопустимым, потому что оно указывает на ту же самую освобожденную память, на которую лучше всего указать.
Комментарии:
1. Извините, все еще немного на C 😉 Исправлено.
Ответ №3:
Вам нужно знать размер строки.
В (1) Вы бы назначили адрес адреса памяти, который уже был освобожден, вам нужно выполнить другой malloc для match*=malloc(sizestr)
, а затем скопировать его с помощью memmove или strcpy, если вы хотите освободить наилучшим образом.
Если я правильно понял, вы хотите скопировать строку в best, затем освободить память bests и назначить ptr для соответствия? если вы освобождаете большую часть памяти перед перемещением в другое место, вы теряете ее содержимое, и если вы хотите скопировать ее в другое место, сначала вам нужно выделить память, куда вы хотите ее скопировать, поэтому для этого кода вам нужно 2 mallocs.
Ответ №4:
Если бы мне пришлось освобождать память в (1), а не в (2), как бы я это сделал, чтобы в match все еще было то, что содержалось в best?
Если вы free
в position (1)
, невозможно сделать это так, чтобы match
все еще было то, что содержалось в best
.
Должен ли я выполнять strcpy, чтобы копировать наилучшим образом, чтобы соответствовать? Если да, должен ли я выполнить другой malloc в foo?
match = best;
С помощью приведенного выше оператора оба указывают на одно и то же местоположение. Таким образом, в strcpy
этом вообще нет необходимости. Для этого выделите память для match
указания, длина которого best 1
равна, а затем выполните strcpy
.
Ответ №5:
Копирование значения указателя не копирует базовую память. Так что либо не делайте этого, free(best)
пока не закончите с match
, либо вам понадобится malloc
новый буфер и, например, memcpy()
содержимое из одного буфера в другой.
Ответ №6:
Да, вы можете malloc
и strcpy
:
match = malloc(strlen(best) 1);
strcpy(match, best);
Но, если ваша реализация предусматривает это, вы можете использовать strdup()
функцию, которая намного проще:
match = strdup(best);
Если у вас еще нет strdup(), хорошей идеей будет создать его самостоятельно.
Ответ №7:
Ваше текущее назначение просто присваивает указатели одному и тому же буферу. Если вы затем free()
удалите этот буфер, вы удалите то, что здесь содержится (и, следовательно, разыменовывать его — плохая идея).
Вам не нужно использовать strcpy()
для копирования наилучшего соответствия — вам будет лучше освободить его после printf()
(или последней точки, в которой это необходимо). Нет смысла чрезмерно усложнять ситуацию дополнительным вызовом функции или шестью, просто помните о free()
памяти, которую вы выделили в конце каждой функции!