Last active
May 6, 2021 02:17
-
-
Save JoshCheek/0d217bcdb2d2f8c6497b609d873c9838 to your computer and use it in GitHub Desktop.
Finding an object's referrers
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| require 'objspace' | |
| require 'fiddle' | |
| require 'json' | |
| def heap | |
| $heap ||= ObjectSpace | |
| .dump_all(output: :string) | |
| .lines.map { JSON.parse _1, symbolize_names: true } | |
| .reject { |obj| %w[ROOT IMEMO DATA].include? obj[:type] } # probably overzealous | |
| end | |
| public def referrers | |
| my_addr = JSON.parse(ObjectSpace.dump self, output: :string)['address'] | |
| heap.select { |obj| obj[:references]&.include? my_addr } # find referrers | |
| .filter_map { |obj| obj[:address] } # get their hex address if they have one | |
| .map { |addr| addr[2..-1].to_i(16) } # convert to int address | |
| .map { |addr| Fiddle::Pointer.new(addr).to_value } # convert to Ruby reference | |
| end | |
| User = Struct.new :id, :name | |
| Users = Struct.new :all | |
| user1 = User.new 123, "Josh" | |
| user2 = User.new 456, "Sal" | |
| @users = Users.new [user1, user2] | |
| # "Josh" shows up somewhere in the app | |
| # We can see it came from User 123 | |
| # Which came from an array | |
| # Stored by Users#all | |
| # stored by main (in `@users`, but main's inspect doesn't show its ivars) | |
| user1.name # => "Josh" | |
| .referrers.first # => #<struct User id=123, name="Josh"> | |
| .referrers.first # => [#<struct User id=123, name="Josh">, #<struct User id=456, name="Sal">] | |
| .referrers.first # => #<struct Users all=[#<struct User id=123, name="Josh">, #<struct User id=456, name="Sal">]> | |
| .referrers.first # => main |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment