Ruby-debug does not hit breakpoints at class-methods

ruby-1.8.6-p369
ruby-debug-0.10.3

How to set breakpoints at class-methods without editing source of
library files? And without line numbers?

$ cat test.rb
require ‘ruby-debug’

class Aaa
def self.cl_aaa
puts ‘A A A’
end
def initialize
@aaa = ‘a a a’
end
def aaa
puts @aaa
end
end

debugger

a = Aaa.new
Aaa.cl_aaa
a.aaa

$ ruby test.rb
< or >
$ rdebug test.rb
test.rb:
a = Aaa.new
(rdb:1) b Aaa:cl_aaa
Breakpoint 1 at Aaa::cl_aaa
(rdb:1) b Aaa:aaa
Breakpoint 2 at Aaa::aaa

(rdb:1) i b
Num Enb What
1 y at Aaa:cl_aaa
2 y at Aaa:aaa

(rdb:1) cont
A A A
Breakpoint 2 at Aaa:aaa
test.rb:<lineno of ‘def aaa’>
def aaa

(rdb:1) i b
Num Enb What
1 y at Aaa:cl_aaa
2 y at Aaa:aaa
breakpoint already hit 1 time
(rdb:1) cont
a a a
$

The same result if it was used ‘#’ or ‘.’ instead of ‘:’, i.e.
‘Class#method’ or ‘Class.method’.

…and more

$ ruby -v
ruby 1.8.6 (2007-03-13 patchlevel 0) [i686-darwin8.11.1]

$ rdebug -v
ruby-debug 0.10.3


require ‘rubygems’
require ‘ruby-debug’

class A
def initialize
end

def sayhi #line 8
puts “hello”
end

def A.show
puts “A”
end
end

a = A.new
A.show
a.sayhi

$ rdebug r2test.rb
/Users/me/2testing/dir1/r2test.rb:1
require ‘rubygems’

(rdb:1) break A.show
*** Unknown class A.

(rdb:1) break 8
Breakpoint 1 file /Users/me/2testing/dir1/r2test.rb, line 8

(rdb:1) continue
Breakpoint 1 at r2test.rb:8
/Users/me/2testing/dir1/r2test.rb:8
def sayhi

(rdb:1) break A.show
Breakpoint 2 at A::show

(rdb:1) continue
A
hello
$

Sys P. wrote:

$ rdebug r2test.rb
/Users/me/2testing/dir1/r2test.rb:1
require ‘rubygems’

(rdb:1) break A.show
*** Unknown class A.

It is normal. Because class A is not defined at this point yet. In case
when rdebug is lauched, it stops at the first line. But it is possible
to set break at any line of source by line number.

In your opinion, what does the rest of the debug session do?

But why ruby-debug does not stop at class-methods when class is already
loaded, though it stops at instance-methods?

The debugger won’t stop at instance methods for me:


require ‘rubygems’
require ‘ruby-debug’

class A
def initialize
end

def A.show
puts “A”
end

def sayhi
puts “hello”
end
end

debugger
puts “pausing here”

a = A.new
a.sayhi
A.show

$ ruby r2test.rb
r2test.rb:18
puts “pausing here”

(rdb:1) break a.sayhi
*** Unknown class a.

(rdb:1) break sayhi
*** Invalid breakpoint location: sayhi.
(rdb:1)

$ rdebug r2test.rb
/Users/me/2testing/dir1/r2test.rb:1
require ‘rubygems’

(rdb:1) break A.show
*** Unknown class A.

It is normal. Because class A is not defined at this point yet. In case
when rdebug is lauched, it stops at the first line. But it is possible
to set break at any line of source by line number.

But why ruby-debug does not stop at class-methods when class is already
loaded, though it stops at instance-methods?

…or I guess this would be a better example:


require ‘rubygems’
require ‘ruby-debug’

class A
def initialize
end

def A.show
puts “A”
end

def sayhi
puts “hello”
end
end

a = A.new

debugger
puts “pausing here”

puts “hello”
puts “world”

a.sayhi
A.show

puts “the end”

$ ruby r2test.rb
r2test.rb:21
puts “pausing here”

(rdb:1) list
[16, 25] in r2test.rb
16
17
18 a = A.new
19
20 debugger
=> 21 puts “pausing here”
22
23 puts “hello”
24 puts “world”
25

(rdb:1) break a.sayhi
*** Unknown class a.

(rdb:1) break sayhi
*** Invalid breakpoint location: sayhi.

(rdb:1) break A.show
Breakpoint 1 at A::show

(rdb:1) continue
pausing here
hello
world
hello
A
the end

To 7stud. These are all normal, except class-method, as i wrote.

In you example ‘a.sayhi’ and especially ‘sayhi’ - is not correct
refernces to instance metod. But ‘A.sayhi’ is it. Or ‘A:sayhi’, or
‘A#sayhi’.

You should better understand the difference between class and instanse
methods.

It is all ok. Except subject of these posts.

On 8/22/09, Sys P. [email protected] wrote:

ruby-1.8.6-p369
ruby-debug-0.10.3

How to set breakpoints at class-methods without editing source of
library files? And without line numbers?

My recollection is that ruby-debug does not allow setting breakpoints
by method name. For that, you need to use the older debug.rb (in
ruby’s stdlib). Add -rdebug to the command line when you start the
interpreter. And you have to put up with the much slower performance
of debug.rb. (Often than doesn’t matter, tho.)

On Sun, Aug 23, 2009 at 11:50 PM, Sys P.[email protected] wrote:

To 7stud. These are all normal, except class-method, as i wrote.

In you example ‘a.sayhi’ and especially ‘sayhi’ - is not correct
refernces to instance metod. But ‘A.sayhi’ is it. Or ‘A:sayhi’, or
‘A#sayhi’.

You should better understand the difference between class and instanse
methods.

It is all ok. Except subject of these posts.

I don’t know about rdebug in this case (I can’t remember trying to set
breakpoints on method names, I usually just use the line number or set
the breakpoint in textmate using the rubyamp bundle), but normal
nomenclature, given a class A

A#meth - refers to an instance method of A
A::meth - refers to a class method of A (note the double colon)

This is what RI uses. RI also appears to accept

A.meth

which will give documentation on an instance method named meth is A
has one, or if not a class method named meth if there is one.

For example ri IO.read gives info on IO#read (IO has both IO::read
and IO#read), while IO.select gives info on IO::select

And RI doesn’t appear to understand A:meth


Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

Oh. It makes something more clear.

http://www.ruby-doc.org/core/classes/Class.html
Google: “ruby metaclasses”.
http://www.klankboomklang.com/2007/10/05/the-metaclass/
http://vision-media.ca/resources/ruby/understanding-ruby-metaclasses

Fixed in ruby-debug 1.9 (although it hasn’t uploaded yet; GitHub is
pretty slow today). I’ve also submitted a patch to RubyForge for 1.8.

Mark M. wrote:

Fixed in ruby-debug 1.9 (although it hasn’t uploaded yet; GitHub is
pretty slow today). I’ve also submitted a patch to RubyForge for 1.8.

I’m curious: if the feature is valuable, why not make it more general
and have break stop at a match to a specified string or a regex, for
example:

break “a.sayhi”

or

break /a.sayhi/

7stud – wrote:

Mark M. wrote:

Fixed in ruby-debug 1.9 (although it hasn’t uploaded yet; GitHub is
pretty slow today). I’ve also submitted a patch to RubyForge for 1.8.

I’m curious: if the feature is valuable, why not make it more general
and have break stop at a match to a specified string or a regex, for
example:

break “a.sayhi”

or

break /a.sayhi/

Well, that’s certainly possible, but at first glance, that to me looks
like feature-itis. IOW, I don’t know that it’s terribly useful, and it
might tend to confuse users. I could be wrong.

Rick Denatale wrote:

I don’t know about rdebug in this case (I can’t remember trying to set
breakpoints on method names, I usually just use the line number or set
the breakpoint in textmate using the rubyamp bundle), but normal
nomenclature, given a class

A#meth - refers to an instance method of A
A::meth - refers to a class method of A (note the double colon)

This is what RI uses. RI also appears to accept

A.meth

which will give documentation on an instance method named meth is A
has one, or if not a class method named meth if there is one.

For example ri IO.read gives info on IO#read (IO has both IO::read
and IO#read), while IO.select gives info on IO::select

And RI doesn’t appear to understand A:meth

I know about conventions. And know about theoretical difference between
class and instance methods. And also know that rdebug does not fully
correspond these lexical conventions.

But this case in point is technical aspects of rdebug. Though I do not
say anything against possibility of better syntax.

As it is seen, when during setting breakpoint it is pointed to some
class and some method (no matter in which syntax), rdebug at runtime
checks the class existing and just remembers the method name for later
binding without checking.

The problem is what later rdebug searches the method only in the
dictionary of instance methods of the class, but neither of
class-methods nor in dictionary singleton methods. I do not know how
these dictionaries are realized, I just see the fact.

I suppose what class methods and singleton methods of class-object are
the same things.

It is very useful when there are many dynamically generated code-objects
and source code does not exist.

Sys P. wrote:

It is very useful when there are many dynamically generated code-objects
and source code does not exist.

OK, I can see that. Please open a feature request at:
http://rubyforge.org/projects/ruby-debug19/

Mark M. wrote:

Well, that’s certainly possible, but at first glance, that to me looks
like feature-itis. IOW, I don’t know that it’s terribly useful, and it
might tend to confuse users. I could be wrong.

Is it possible to make so that one can set breakpoints at any Method or
Proc instance, or at any object with “breakable” interface at all?

It may be to make two modes of debugger for ordinary and experienced
users.

Or else it will not be known, is it needed or not, until someone will be
able to play with it. Only practice may show it, if someone will get
this freedom.

Sys P. wrote:

Unfortunately, on my distro they have not yet made friendship between
1.8 and 1.9, rubygems conflicts :frowning: And I am depending on 1.8 now. So I
shall not have been able to test it on 1.9 at nearly time.

A backport to 1.8 might be possible; hard to say at this point.

OK, I can see that. Please open a feature request at:
http://rubyforge.org/projects/ruby-debug19/

Thank you for your attention. I shall have done it as soon as I can. I
shall have tryed to better formulate the request.

Unfortunately, on my distro they have not yet made friendship between
1.8 and 1.9, rubygems conflicts :frowning: And I am depending on 1.8 now. So I
shall not have been able to test it on 1.9 at nearly time.

Ok. I shall have practised in it anyway, because it is needed to me.
Just a little shall learn tracing interface of objects. I think it must
be an elegant solution without any hack. Or else why does tracing
interface need, if it is not used completely by debugger.

I can’t write on Python anymore after I have known Ruby better :slight_smile: