25 / 25 / 4
Регистрация: 21.10.2012
Сообщений: 391
1

Утечка памяти при рекурсии

29.05.2015, 10:10. Показов 2563. Ответов 10
Метки нет (Все метки)

Здравствуйте. Столкнулся ч тем, что я, похоже, неправильно составил алгоритм рекурсии. При запуске получаю ошибку связанную с памятью. Ошибка: Fatal error: Allowed memory size of 67108864 bytes exhausted (tried to allocate 130968 bytes)

Код:
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
    protected function findLogin($nmUser, $snUser, $i = 1) {
        $nmUser = $this->translit($nmUser);
        $snUser = $this->translit($snUser);
        $login = mb_substr($nmUser, 0, $i) . '.' . $snUser;
        $this->res = $this->link->query('SELECT COUNT(*) FROM `users` WHERE `login` = "'.$login.'"');
        if (!$this->res)
            $this->writeErrors("Ошибка проверки логина!\nПопробуйте снова!", "/admin/registration/");
        $this->row = $this->res->fetch_array();
        if ($this->row[0] == 0) 
            return $login;
        else
            $this->findLogin($nmUser, $snUser, $i++);
    }
Вызов
PHP
1
$this->login = $this->findLogin($this->nmUser, $this->snUser);
__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
29.05.2015, 10:10
Ответы с готовыми решениями:

Будет ли утечка памяти?
Допустим у меня есть массив $array в котором записаны 10 чисел. Я захотел избавиться от элементов...

Утечка памяти
Здравствуйте. Столкнулся со следующей проблемой. Код: $countQuery = 'SELECT COUNT(*) FROM...

Утечка памяти в PHP
Всем привет! Вот столкнулся с проблемой утечки памяти. Есть скрипт, который выполняет...

Утечка памяти при ping'e...
OS: Win7 VS 8 ************ Всем привет. Помогите определить и устранить утечку памяти. ...

10
Эксперт PHP
5502 / 3971 / 1417
Регистрация: 06.01.2011
Сообщений: 10,938
29.05.2015, 10:16 2
А зачем такая функция?
0
25 / 25 / 4
Регистрация: 21.10.2012
Сообщений: 391
29.05.2015, 10:28  [ТС] 3
Цитата Сообщение от Para bellum Посмотреть сообщение
А зачем такая функция?
Если логин сгенерированный системой из имени и фамилии пользователя уже существует, то она изменяет алгоритм подбора логина.
т.е. изначально логин равен 1 буквы имени.фамилия
Если такой логин уже есть, то функция должна пойти вновь и взять уже 2буквы имени.фамилия.
Ну и так далее. Только надо еще предусмотреть, если в имени букв не осталось, но это я допишу. Что скажете?
0
Эксперт PHP
5502 / 3971 / 1417
Регистрация: 06.01.2011
Сообщений: 10,938
29.05.2015, 10:36 4
Вообще не представляю, зачем такое может понадобиться.
А чтобы не было утечки, попробуйте так:
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
    protected function findLogin($nmUser, $snUser, $i = 1) {
        $nmUser = $this->translit($nmUser);
        $snUser = $this->translit($snUser);
        $login = mb_substr($nmUser, 0, $i) . '.' . $snUser;
        $this->res = $this->link->query('SELECT COUNT(*) FROM `users` WHERE `login` = "'.$login.'"');
        if (!$this->res)
            $this->writeErrors("Ошибка проверки логина!\nПопробуйте снова!", "/admin/registration/");
        $this->row = $this->res->fetch_array();
        if ($this->row[0] == 0) 
            return $login;
        else{
            $this->row = $this->res = null;
            unset($login);
            
            $this->findLogin($nmUser, $snUser, $i++);
        }
    }
Добавлено через 1 минуту
А ещё может быть проблема в writeErrors.
0
25 / 25 / 4
Регистрация: 21.10.2012
Сообщений: 391
29.05.2015, 11:41  [ТС] 5
Цитата Сообщение от Para bellum Посмотреть сообщение
Вообще не представляю, зачем такое может понадобиться.
А чтобы не было утечки, попробуйте так:
Не помогло, увы.
Цитата Сообщение от Para bellum Посмотреть сообщение
А ещё может быть проблема в writeErrors.
writeErrors только и делает, что ставит куку и редиректит на нужную страницу. Да и по идее, writeErrors вообще не должен вызываться т.к. проблем с запросом не должно быть. Щас проверю, что возвращает запрос. Быть может это я накосячил.

Добавлено через 28 минут
Цитата Сообщение от Para bellum Посмотреть сообщение
А ещё может быть проблема в writeErrors.
Вот так утечки памяти нет. Только логин приходит пустой из функции
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    protected function findLogin($nmUser, $snUser, $link, $i = 1) {
        $this->link = $link;
        if (mb_strlen($nmUser) > $i)
            $login = mb_substr($nmUser, 0, mb_strlen($nmUser)) . '.' . $snUser . mt_rand(0, $i);
        else {
            $login = mb_substr($nmUser, 0, $i) . '.' . $snUser;
            $res = $this->link->query('SELECT COUNT(*) FROM `users` WHERE `login` = "'.$login.'"');
            if (!$res)
                $this->writeErrors("Ошибка проверки логина!\nПопробуйте снова!", "/admin/registration/");
            $row = $res->fetch_array();
            if ($row[0] == 0)
                return $login;
            else {
                $res->close();
                unset($login);
                $this->findLogin($nmUser, $snUser, $i++);
            }
        }
    }
Добавлено через 27 минут
Если кому интересно - решение так и не нашел. Поэтому ушел от рекурсии в сторону цикла:
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    protected function findLogin($nmUser, $snUser) {
        for ($i=1;true; $i++) {
            if (mb_strlen($nmUser) <= $i)
                $login = mb_substr($nmUser, 0, mb_strlen($nmUser)) . '.' . $snUser . mt_rand(0, $i);
            else
                $login = mb_substr($nmUser, 0, $i) . '.' . $snUser;
            $this->link = $this->connectDB();
            $this->res = $this->link->query('SELECT COUNT(*) FROM `users` WHERE `login` = "'.$login.'"');
            if (!$this->res)
                $this->writeErrors("Ошибка проверки логина!\nПопробуйте снова!", "/admin/registration/");
            $this->row = $this->res->fetch_array();
            if ($this->row[0] == 0)
                return $login;
        }
    }
Все работает. Тему можно закрывать)
1
204 / 26 / 5
Регистрация: 22.05.2015
Сообщений: 357
29.05.2015, 11:49 6
Цитата Сообщение от M1lleniuM Посмотреть сообщение
PHP
1
this->findLogin($nmUser, $snUser, $i++);
$i++ замени на $i + 1.
0
Эксперт PHP
5502 / 3971 / 1417
Регистрация: 06.01.2011
Сообщений: 10,938
29.05.2015, 12:02 7
Цитата Сообщение от cybercitizen Посмотреть сообщение
$i++ замени на $i + 1.
А что изменится?
0
204 / 26 / 5
Регистрация: 22.05.2015
Сообщений: 357
29.05.2015, 12:20 8
Всё изменится. Инкрементить в рекурсивных вызовах крайне нежелательно потому как во-первых при обратом возврате в функцию значение переменной уже другое (т.е. надо очень хорошо понимать где это возможно), во-вторых в данном случае значение в следующий рекурсивный вызов передается то же что и было, что и вызывает переполнение. Попробуй запустить
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
    function foo ($i = 1) {
        if($i > 10) {
            return 0;
        }
        else {
            echo $i + " ";
            foo($i++);
            echo $i + " ";  
        }
    }
 
    foo();
?>
0
Эксперт PHP
5502 / 3971 / 1417
Регистрация: 06.01.2011
Сообщений: 10,938
29.05.2015, 12:42 9
Цитата Сообщение от cybercitizen Посмотреть сообщение
в данном случае значение в следующий рекурсивный вызов передается то же что и было
Блин, точно. Что-то я... Тогда нужно использовать предварительное увеличение (prefix increment).
0
204 / 26 / 5
Регистрация: 22.05.2015
Сообщений: 357
29.05.2015, 12:47 10
а еще лучше раз и навсегда отучить себя использовать инкремент/декремент в рекурсивных функциях.
0
Эксперт PHP
5502 / 3971 / 1417
Регистрация: 06.01.2011
Сообщений: 10,938
29.05.2015, 13:05 11
Разницы нет, что префиксный инкремент, что "вручную" добавлять единицу. Сработает одинаково. Главное использовать правильно, а не так, как изначально было (постфиксный инкремент).
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
29.05.2015, 13:05
Помогаю со студенческими работами здесь

Утечка памяти при удалении
Здравствуйте! Возникла проблема при удалении последнего элемента из двусвязного списка. Вот...

Утечка памяти при отправке запросов
Подскажите как решить задачу (отправления большого количества запросов за один раз и повторение...

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

Утечка памяти при вызове функции
Здравствуйте. Объясните пожалуйста почему возникает утечка памяти при вызове функции...

Утечка памяти при декодировании видео
Доброго времени суток! Пишу плеер видео, на этапе декодирования кадров и их вывода столкнулся с...

Утечка памяти при рисование GUI
Здравствуйте, нашел у себя в коде утечку памяти и не знаю как ее исправить, вот код где утечка...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2022, CyberForum.ru