Потенциальные утечки памяти

959 views
Skip to first unread message

Andrey Velikoredchanin

unread,
Jan 25, 2017, 6:05:32 AM1/25/17
to golang-ru
Всем привет!

Можете подсказать где найти информацию о том, какие приемы могут вызывать потенциальные утечки памяти?

Спасибо.

ma...@kevac.org

unread,
Jan 25, 2017, 7:41:22 AM1/25/17
to golang-ru
Если брать обычное понимание фразы "утечка памяти", то в Go добиться ее не так-то просто. Ведь GC подберет всю память, на которую уже нет ссылок. Придется использовать unsafe, cgo и вызов malloc, например.

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

--
Вы получили это сообщение, поскольку подписаны на группу "Golang Russian".
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес golang-ru+...@googlegroups.com.
Чтобы настроить другие параметры, перейдите по ссылке https://groups.google.com/d/optout.

Andrey Velikoredchanin

unread,
Jan 25, 2017, 7:51:17 AM1/25/17
to golang-ru
Т.е. в golang под "освобождением памяти" понимается либо потеря контекста соответствующей переменной либо ее об-nil-ение? Даже если создается канал через make, если на него больше нет ссылок он будет освобожден?

25 января 2017 г., 15:41 пользователь ma...@kevac.org <ma...@kevac.org> написал:
Если брать обычное понимание фразы "утечка памяти", то в Go добиться ее не так-то просто. Ведь GC подберет всю память, на которую уже нет ссылок. Придется использовать unsafe, cgo и вызов malloc, например.

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

On Wed, Jan 25, 2017 at 2:05 PM Andrey Velikoredchanin <uncle...@gmail.com> wrote:
Всем привет!

Можете подсказать где найти информацию о том, какие приемы могут вызывать потенциальные утечки памяти?

Спасибо.

--
Вы получили это сообщение, поскольку подписаны на группу "Golang Russian".
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес golang-ru+unsubscribe@googlegroups.com.

Чтобы настроить другие параметры, перейдите по ссылке https://groups.google.com/d/optout.

--
Вы получили это сообщение, поскольку подписаны на группу "Golang Russian".
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес golang-ru+unsubscribe@googlegroups.com.

ma...@kevac.org

unread,
Jan 25, 2017, 7:55:27 AM1/25/17
to golang-ru
Да.

On Wed, Jan 25, 2017 at 3:51 PM Andrey Velikoredchanin <uncle...@gmail.com> wrote:
Т.е. в golang под "освобождением памяти" понимается либо потеря контекста соответствующей переменной либо ее об-nil-ение? Даже если создается канал через make, если на него больше нет ссылок он будет освобожден?

25 января 2017 г., 15:41 пользователь ma...@kevac.org <ma...@kevac.org> написал:
Если брать обычное понимание фразы "утечка памяти", то в Go добиться ее не так-то просто. Ведь GC подберет всю память, на которую уже нет ссылок. Придется использовать unsafe, cgo и вызов malloc, например.

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

On Wed, Jan 25, 2017 at 2:05 PM Andrey Velikoredchanin <uncle...@gmail.com> wrote:
Всем привет!

Можете подсказать где найти информацию о том, какие приемы могут вызывать потенциальные утечки памяти?

Спасибо.

--
Вы получили это сообщение, поскольку подписаны на группу "Golang Russian".
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес golang-ru+...@googlegroups.com.

Чтобы настроить другие параметры, перейдите по ссылке https://groups.google.com/d/optout.

--
Вы получили это сообщение, поскольку подписаны на группу "Golang Russian".
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес golang-ru+...@googlegroups.com.

Чтобы настроить другие параметры, перейдите по ссылке https://groups.google.com/d/optout.

--
Вы получили это сообщение, поскольку подписаны на группу "Golang Russian".
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес golang-ru+...@googlegroups.com.

Vladimir Skipor

unread,
Jan 26, 2017, 2:48:42 AM1/26/17
to Golang Russian
Как уже написали, чтобы дать утечь памяти, нужно не освободить какие-то ресурсы. Вместе с ними может утечь и память. 
Один из классических случаев утечки  в Go, это утечка горутин. При утечке горутины утекает её стек и память на которую ссылается только она. 
Происходит это, когда горутина блокируется на примитиве синхронизации, без шанса разблокироваться. Типичные примеры: не буферизованная запись в канал из которого не читают, чтения из канала в который не пишут и не закрывают, взаимная блокировка (дедлок) на мьютексе, не отпускание взятой блокировки.
Соответсвенно приемы которые позволяют избегать подобного.
1) писать в буферизованные каналы 
2) выполнять блокирующее чтение/запись в select совместно с чтением которое гарантированно произойдет. Обычно, ctx.Done() контекста который гарантированно отменится.
3) Иметь ацикличную иерархию взятия блокировок. Это гарантирует отсутсвие дедлоков.
4) Всегда отпускать взятые блокировки. 

Второй по популярности случай утечки ресурса: не вызов, или неправильный вызов, Close() метода, или аналогичных функций освобождающих ресурсы (Unlock(), Cancel() и прочее). 
В Close() могут закрываться сокеты, освобождаться память взятая в cgo, закрываться каналы из которых происходит блокирующее чтение.
Не вызвать можно просто забыв, или же вызвать их вне defer и пропустить этот вызов получив панику. 
Ещё есть вариант вызывать в defer в функции которая не завершится - в бесконечном цикле, как пример. 
среда, 25 января 2017 г., 14:05:32 UTC+3 пользователь Andrey Velikoredchanin написал:

Daniel Podolsky

unread,
Jan 26, 2017, 10:39:04 AM1/26/17
to gola...@googlegroups.com
> 2) выполнять блокирующее чтение/запись в select совместно с чтением которое
> гарантированно произойдет. Обычно, ctx.Done() контекста который
> гарантированно отменится.

есть же секция default для придания селекту неблокируемости

Vladimir Skipor

unread,
Jan 27, 2017, 12:31:51 PM1/27/17
to Golang Russian
Есть, но она не часто применима. Самый типичный паттерн использования select в бекэнде:
ctx, cancel := context.WithTimeout(ctx, config.Timeout)
defer cancel
()
type
Result {Value Type; Err error}
result
:= make(chan Result)
go func
() {
  defer func
() {
   
if r := recover(); r != nil {
      result
<- Result{Err: fmt.Errf("panic: %s\n%s", r, debug.Stack())}
   
}
 
}
  res
, err := foo() // Can panic.
 
select {
 
case result <- Result{res, err}:
 
case <-ctx.Done():
     
// Нельзя использовать default: читающая горутина может не успеть
     
// войти в select к моменту записи. В таком случае, результат будет выкинут
     
// а читающая горутина об этом не узнает.
 
}
}()
baz
() // Can panic.
select {
case res <- result:
 
return res.Value, res.Err
case <-ctx.Done():
  resturn
nil, ctx.Err()
}

Вместо context.Context может использоваться cancel chan struct{}


четверг, 26 января 2017 г., 18:39:04 UTC+3 пользователь Daniel Podolsky написал:
Reply all
Reply to author
Forward
0 new messages