# Scope and RAII

**URL:** <https://www.ruby-forum.com/t/scope-and-raii/89980>\
**Category:** Ruby\
**Created:** [March 24, 2007, 3:45pm UTC](https://www.ruby-forum.com/t/scope-and-raii/89980 "2007-03-24T15:45:36Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [March 24, 2007, 3:45pm UTC](https://www.ruby-forum.com/t/scope-and-raii/89980/1 "2007-03-24T15:45:36Z")

</div>

def scope(\*args)  
yield(\*args)  
end

scope(Array.new) { |array|  
array.push 1  
array.push 7  
array.push 11  
puts array.join(",")  
}

# here the variable ‘array’ is gone – is it deallocated?

I am interested in using ruby for some resource-intensive tasks. In  
the above example, imagine Array replaced with some resource-tied  
class written in C, for example a set of hardware textures.

Does ruby make a special effort to release a variable when it goes out  
of scope? The canonical example is

File.open(“foo.txt”) { |f|  
print f.read  
}

# internal file handle released here

Is this behavior a general rule, or just a special case for  
File.open()? And is it released immediately or upon the  
next GC pass?

Thanks,  
Jeff

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [March 24, 2007, 4:27pm UTC](https://www.ruby-forum.com/t/scope-and-raii/89980/2 "2007-03-24T16:27:50Z")

</div>

removed\_email\_address@domain.invalid wrote:

> next GC pass?  
> The file handle should be released ASAP if you use:

file = File.open(“foo”, “r”) #opens foo in read-only mode  
file.readlines { |f| print f } #prints each line  
file.close #closes the file handle.

In that case, you can use the mixins from IO via File, including, but  
not limited, to IO#close.

IMHO, it is a good idea to tell Ruby the mode it should open a file,  
too.[0]

Disclaimer: I’m still a Ruby nuby, and don’t know anything about the  
inner workings of Ruby itself.

Bibliography:  
[0] [Ruby | zenspider.com | by ryan davis](http://www.zenspider.com/Languages/Ruby/QuickRef.html#15)

–  
Phillip “CynicalRyan” Gawlowski

Rule of Open-Source Programming #20:

Open Code != Good Code

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [March 24, 2007, 4:45pm UTC](https://www.ruby-forum.com/t/scope-and-raii/89980/3 "2007-03-24T16:45:53Z")

</div>

On Mar 24, 11:27 am, Phillip G. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> file = File.open(“foo”, “r”) #opens foo in read-only mode  
> file.readlines { |f| print f } #prints each line  
> file.close #closes the file handle.

I should have mentioned why I put “RAII” in the subject. The coding  
style you show above is exactly what I’m trying to avoid.

> **[Resource acquisition is initialization](https://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization)**
>
> Resource acquisition is initialization (RAII) is a programming idiom used in several object-oriented, statically-typed programming languages to describe a particular language behavior. In RAII, holding a resource is a class invariant, and is tied to object lifetime. Resource allocation (or acquisition) is done during object creation (specifically initialization), by the constructor, while resource deallocation (release) is done during object destruction (specifically finalization), by the RAII ...

I’ll preemptively ask that we not discuss the necessity of RAII; as  
a game programmer it is a necessity for me.

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [March 24, 2007, 5:04pm UTC](https://www.ruby-forum.com/t/scope-and-raii/89980/4 "2007-03-24T17:04:56Z")

</div>

removed\_email\_address@domain.invalid wrote:

> # here the variable ‘array’ is gone – is it deallocated?

No. In general, it won’t be deallocated until the next GC pass.

> # internal file handle released here
> 
> Is this behavior a general rule, or just a special case for  
> File.open()?  
> The release of a file handle is a different case to freeing a variable.  
> You might be thinking of the release of a file handle as being handled  
> by a destructor - that’s not what’s happening. Ruby doesn’t have  
> destructors. It does have finalizers, but they aren’t the same (mainly  
> because they’re not guaranteed to be called, although I’ll have to defer  
> to someone more knowledgeable than myself as to the details). In  
> essence, as I understand it File.open with a block does something  
> equivalent to this (very)pseudocode:

class File  
def open(filename, mode)  
file\_handle = fopen(filename, mode)  
yield(File.create\_from\_handle(file\_handle))  
fclose(file\_handle)  
end  
end

> And is it released immediately or upon the  
> next GC pass?  
> It’s released immediately, but that’s as a consequence of the code in  
> File.open rather than because it’s gone out of the block’s scope.

Hope this helps,

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [March 24, 2007, 5:08pm UTC](https://www.ruby-forum.com/t/scope-and-raii/89980/5 "2007-03-24T17:08:57Z")

</div>

Alex Y. wrote:

> > }
> > 
> > # here the variable ‘array’ is gone – is it deallocated?
> 
> No. In general, it won’t be deallocated until the next GC pass.  
> I should have pointed out here (in case you hadn’t spotted it already)  
> that the variable is utterly distinct from the object to which it  
> refers. The variable can go out of scope and the object may not be  
> collected at all - it entirely depends on what else has a reference to  
> that object.

Hope that’s clear,

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [March 24, 2007, 5:16pm UTC](https://www.ruby-forum.com/t/scope-and-raii/89980/6 "2007-03-24T17:16:58Z")

</div>

On Sat, 24 Mar 2007 removed\_email\_address@domain.invalid wrote:

> }
> 
> # here the variable ‘array’ is gone – is it deallocated?

array is merely a label - a handle. the variable is references, the  
one  
created by

Array.new

still exists. you can prove this to yourself

harp:~ \> cat a.rb  
def scope(\*args)  
yield(\*args)  
end

scope(Array.new) { |array|  
array.push 1  
array.push 7  
array.push 11  
puts array.join(",")  
}

ObjectSpace.each\_object(Array){|obj| p obj}

harp:~ \> ruby a.rb  
1,7,11  
[[1, 7, 11]]  
[1, 7, 11]  
[]  
[]  
[]  
[]  
["/home/ahoward//lib/ruby/site\_ruby/1.8",  
“/home/ahoward//lib/ruby/site\_ruby/1.8/i686-linux”,  
“/home/ahoward//lib/ruby/site\_ruby”, “/home/ahoward//lib/ruby/1.8”,  
“/home/ahoward//lib/ruby/1.8/i686-linux”, “.”]  
[:utime, :stime, :cutime, :cstime]

in fact, your scoping method has managed to create three of them 😉

one here

scope(Array.new)  
^^^^^^^^^

one here

def scope(\*args)  
^^^^

and one here

```
 yield(*args)
        ^^^^

```

so this probably isn’t the best way to conserve on resource utilization!  
😉

> }
> 
> # internal file handle released here
> 
> Is this behavior a general rule, or just a special case for  
> File.open()? And is it released immediately or upon the  
> next GC pass?

there are two issues here

- the fd, which **is** released at the end of the block

- any ruby variables, which will only be freed by the GC

in the case of the first the only reason it’s freed is because it’s  
coded to do  
exactly that, you can imagine it like

class File  
def open path, mode, &b  
fd = open\_file path, mode  
b.call fd  
ensure  
fd.close  
end  
end

this is the general pattern you use to force resource deallocation.  
note that  
it’s your responsiblity and that ruby does nothing special to make sure  
it  
happens.

-a

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [March 26, 2007, 11:58pm UTC](https://www.ruby-forum.com/t/scope-and-raii/89980/7 "2007-03-26T23:58:13Z")

</div>

On 3/24/07, removed\_email\_address@domain.invalid [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> there are two issues here
> 
> - the fd, which **is** released at the end of the block

Released in the sense that File.open closes the file handle after  
execution of the block when a block is given.

> - any ruby variables, which will only be freed by the GC

I’ve got to quibble with this. It’s objects which are freed by the  
GC, not variables. The distinction between objects and  
variables(references) is subtle, but it also trips up a lot of newbies  
which is why I’m going into this.

Ruby variables are simply ‘slots’ which reference objects.

Method or block temporaries (pretty much the same thing in 1.8) and  
method parameters exist on the call stack and go away when the call  
stack is popped.

Instance variables are value slots in a hash table pointed to by an  
object. These variables live as long as the object does, or until  
they are removed with remove\_instance\_variable.

Class variables and Constants are similarly associated with a Class  
or Module object, and Globals are kept in a global registry.

So other than the variables which exist on the call stack, variables  
are never automatically freed.

But an object becomes a candidate to be freeded (actually to have its  
space reclaimed) by the GC when there are no variables reachable by  
following chains of variable references starting with either variables  
on the stacks of any threads, or constants (actually constants in the  
root namespace)

## Also this only makes the object a candidate for GC, there is no guarantee of how soon, if ever, after all references to an object are gone that an object will be reclaimed by the GC. Which is why it’s a bad idea to rely on finalization to clean up external resources associated with an object.

Rick DeNatale

My blog on Ruby  
[http://talklikeaduck.denhaven2.com/](http://talklikeaduck.denhaven2.com/)

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [March 24, 2007, 6:06pm UTC](https://www.ruby-forum.com/t/scope-and-raii/89980/8 "2007-03-24T18:06:09Z")

</div>

Thanks to everyone for the responses. It turns out I was mislead by  
this example I had in mind:

handle = nil  
File.open(“test.txt”, “w”) { |f|  
f.puts “line 1”  
handle = f  
}  
handle.puts “line 2”

In my mind, I thought that assigning “handle” to “f” would prevent the  
file from being closed. But now that I actually run the code, I see  
the exception on the second puts. (In retrospect, I must have been  
thinking in terms of perl.)
