Возврат указателя на автоматическую переменную

У меня была та же проблема, и я решил ее при помощи кода 'сервлета по умолчанию' от кодовой базы Tomcat.

http://svn.apache.org/repos/asf/tomcat/trunk/java/org/apache/catalina/servlets/DefaultServlet.java

DefaultServlet является сервлетом, который служит статическим ресурсам (jpg, HTML, css, gif и т.д.) в Tomcat.

Этот сервлет очень эффективен и имеет некоторых свойства, которые Вы определили выше.

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

  • Ссылки на org.apache.naming.resources пакет могут быть удалены или заменены java.io. Код файла.
  • Ссылки на org.apache.catalina.util пакет являются propably только служебными методами/классами, которые могут быть дублированы в Вашем исходном коде.
  • Ссылки на org.apache.catalina. Класс Globals может быть встроен или удален.

10
задан Lightness Races with Monica 23 June 2011 в 10:42
поделиться

8 ответов

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

[Обновление] : Чтобы иметь возможность вернуть массив, выделенный в функции, вы должны выделить его вне стека (например, в куче), например:

char *test() {
    char* arr = malloc(100);
    arr[0] = 'M';
    return arr;
}

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

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

Нет, утечки не будет, так как он будет уничтожен после завершения getp ();

Это приведет к неопределенному поведению, потому что теперь у вас есть указатель на область памяти, которая больше не хранит то, что вы думаете, что это так, и это может быть использовано кем угодно.

Утечка памяти может произойти, если вы сохраните этот массив в куче, не выполняя вызов free ().

char* getp(){

   char* p = malloc(N);
   //do stuff to p
   return p;
}

int main(){
    char* p = getp();
    //free(p) No leak if this line is uncommented
    return 0;
}

Здесь p не уничтожается, потому что его не в стеке, а в куче. Однако после завершения программы выделенная память не высвобождается, что вызывает утечку памяти (даже если это происходит после завершения процесса).

[ОБНОВЛЕНИЕ]

Если вы хотите вернуть новую c-строку из функции, у вас есть два варианта.

  • Сохранить ее в куче (как пример выше или как этот реальный пример , который возвращает дублированную строку);
  • Передайте параметр буфера

, например:

    //doesnt exactly answer your update question, but probably a better idea.
    size_t foo (const char* str, size_t strleng, char* newstr);

Здесь вам нужно будет где-то выделить память для newstr (может быть стек ИЛИ куча) перед вызовом функции foo. В этом конкретном случае он вернет количество символов в newstr.

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

Это не утечка памяти, потому что память освобождается правильно.

Но это ошибка. У вас есть указатель на нераспределенную память. Он называется висящей ссылкой и является частым источником ошибок в C. Результаты не определены. Когда вы попытаетесь использовать этот указатель, вы не увидите никаких проблем до выполнения.

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

Автоматические переменные уничтожаются в конце вызова функции; вы не можете вернуть на них указатель. То, что вы делаете, можно описать как «возвращение указателя на блок памяти, который раньше содержал s, но теперь не используется (но может все еще что-то в нем есть, по крайней мере, сейчас), и он будет быстро заполнен чем-то остальное полностью. "

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

Это не вызовет утечки памяти, но вызовет неопределенное поведение. Этот случай особенно опасен, потому что указатель будет указывать где-то в стеке программы, и если вы его используете, вы получите доступ к случайным данным. Такой указатель, будучи записанным, также может использоваться для нарушения безопасности программы и выполнения произвольного кода.

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

s - это стековая переменная - ссылка на нее автоматически отменяется в конце функции. Однако ваш указатель недействителен и будет относиться к области памяти, которая может быть перезаписана в любой момент.

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

Никто еще не упомянул другой способ сделать эту конструкцию действительной: сообщить компилятору, что вы хотите, чтобы массив «s» имел «статическую продолжительность хранения» (это означает, что он живет на время жизни программы, как глобальная переменная). Вы делаете это с помощью ключевого слова static:

char *getp()
{
    static char s[] = "hello";
    return s;
}

Обратной стороной этого является то, что теперь имеется только один экземпляр s, совместно используемый при каждом вызове функции getp (). С функцией, которую вы написали, это не имеет значения. В более сложных случаях он может делать не то, что вы хотите.

PS: Обычный вид локальных переменных имеет так называемую «автоматическую продолжительность хранения», что означает, что новый экземпляр переменной создается, когда функция вызывается и исчезает, когда функция возвращается.

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

Я удалил свой предыдущий ответ после помещая код в отладчик и наблюдая за дизассемблированием и окном памяти.

Код в вопросе недействителен и возвращает ссылку на стековую память, которая будет перезаписана.

Эта немного другая версия, однако, возвращает ссылка на фиксированную память и отлично работает:

char *getp()
{
    char* s = "hello";
    return s;
}
1
ответ дан 3 December 2019 в 13:20
поделиться
Другие вопросы по тегам:

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