Undefined method for Symbol on OS X
drbrain |
For the past few months people have been getting messages looking like undefined method `push’ for :compact!:Symbol (NoMethodError) when using DRb on OS X.
Eventually a simpler example of the problem showed up and in [ruby-core:7305] Mauricio Fernandez thought it could be either OS X’s malloc() alignment or the address at which malloc() first returns memory.
Today I decided to figure out what the real problem was. Apple’s documentation showed that malloc() gives you regions of memory aligned on 16 byte boundaries removing the possibility of an alignment problem.
That left only the second possibility, that malloc() on OS X returns memory lower than on most *NIX platforms.
It turns out that low addresses returned by OS X’s malloc() is the culprit. In Ruby a Symbol’s ID is mapped onto a VALUE in memory by sym = ID << 8 | 0x0e so a Symbol’s object_id ends up being a low address, typically outside the range of valid VALUEs.
On FreeBSD it takes many Symbols for a Symbol to overlap a real VALUE since malloc() first returns addresses up around 0×400000. OS X, however, returns addresses around 0xd0000 so it is already overlapping the built-in set of symbols:
p :x.object_id.to_s(16)
p Object.new.object_id.to_s(16)On OS X:
“26e90e”
“e7bce”
The object_id of a newly created objects is already less than the first newly created Symbol. (New objects will first decrease in object_id, then jump up when the next Ruby heap section is allocated.)
On FreeBSD:
“26910e”
“403b536”
Here the first object is well above the first Symbol, so we won’t have to worry about anything until we’ve generated a lot of Symbols.
The full example is in [ruby-core:7401].
Comments are disabled

