Bug #5077

method_missing throws NoMemoryError after inheriting from BasicObject

Added by Farruco Sanjurjo over 2 years ago. Updated over 2 years ago.

[ruby-core:38394]
Status:Rejected
Priority:Normal
Assignee:-
Category:-
Target version:1.9.2
ruby -v:ruby 1.9.2p290 (2011-07-09 revision 32478) [x86_64-linux] Backport:

Description

If a class inherits from BasicObject and then overwrites method_missing like this:

class A < BasicObject
def method_missing(*a)
puts "#{a}"
end
end

And we try it:

A.new.fooooo

The interpreter enters what looks like a loop and then crashes with this trace (in irb):

NoMemoryError: failed to allocate memory
from (irb):3:in method_missing'
from (irb):3:in
methodmissing'
from (irb):3:in method_missing'
from (irb):3:in
method
missing'
from (irb):3:in method_missing'
from (irb):3:in
methodmissing'
from (irb):3:in method_missing'
from (irb):3:in
method
missing'
from (irb):3:in method_missing'
from (irb):3:in
methodmissing'
from (irb):3:in method_missing'
from (irb):3:in
method
missing'
from (irb):3:in method_missing'
from (irb):3:in
methodmissing'
from (irb):3:in method_missing'
from (irb):3:in
method
missing'
from (irb):3:in method_missing'
from (irb):3:in
methodmissing'
from (irb):3:in method_missing'
from (irb):3:in
method
missing'
from (irb):3:in method_missing'
from (irb):3:in
methodmissing'
from (irb):3:in method_missing'
from (irb):3:in
method
missing'
from (irb):3:in method_missing'
from (irb):3:in
methodmissing'
from (irb):3:in method_missing'
from (irb):3:in
method
missing'
from (irb):3:in method_missing'
from (irb):3:in
method_missing'

If we create the same class with the same method_missing but without inheriting from BasicObject it works right.

History

#1 Updated by Benoit Daloze over 2 years ago

Farruco Sanjurjo wrote:

If a class inherits from BasicObject and then overwrites method_missing like this:

class A < BasicObject
def method_missing(*a)
puts "#{a}"
end
end

And we try it:

A.new.fooooo

The interpreter enters what looks like a loop and then crashes with this trace (in irb):

method_missing is called indefinitely recursively because "puts" is not a method in BasicObject.

Only methods available in BasicObject are:
BasicObject.instancemethods # => [:==, :equal?, :!, :!=, :instanceeval, :instanceexec, :send_]

"puts" is usually provided by Kernel#puts. But Kernel is not included in BasicObject.
You could solve this two ways:
* use "::Kernel::puts" instead of "puts" (the documentation about the first :: is being discussed in Bug #5067)
* include Kernel into your class A

#2 Updated by Kenta Murata over 2 years ago

  • Status changed from Open to Rejected
  • Priority changed from High to Normal

BasicObject doesn't include Kernel module.
It is a spec.

Also available in: Atom PDF