deep copy exception: wrong constant name #1681

Closed
luckyruby opened this Issue Apr 26, 2012 · 8 comments

Comments

Projects
None yet
4 participants

I'm running rubinius 2.0.0dev (1.9.3 7f24eb5 yyyy-mm-dd JI) [x86_64-unknown-linux-gnu] on ubuntu 11.10.

In my rails 3.2.3 app, I deep copy an array of hashes using:

def self.deep_copy(o)
  Marshal.load(Marshal.dump(o))
end

The error I get is:

ArgumentError (wrong constant name other_charges_total):
  lib/utility.rb:22:in `deep_copy'
  app/models/rate_shop.rb:618:in `results'
  app/controllers/requests_controller.rb:4:in `AS'
Member

ileitch commented Apr 26, 2012

Are you able to provide easily reproducible steps (with an example data structure) or link to the app if it is public?

I think I've identified the problem.

On MRI, the array that gets generated looks like:

[{:base_rate=>"175.36", :rate_plan=>"D", :xday_rate=>"175.36", :xhr_rate=>"58.45", :cartype=>"STAR", :fees_total=>"0.00", :total_price=>"350.72", :other_charges_total=>0}]

On rbx, the array looks like:

[{:base_rate=>"175.36", :rate_plan=>"D", :xday_rate=>"175.36", :xhr_rate=>"58.45", :cartype=>"STAR", :fees_total=>"124.45", :total_price=>"475.17", :other_charges_total=>#<BigDecimal:7fee20f55650,'0.12445E3',18(36)>}]

Actually I guess it's just a difference in how it's outputted. Still trying to reproduce the issue outside of my rails app.

Member

ileitch commented Apr 26, 2012

Well, :other_charges_total comes out as a BigDecimal in your rbx example and a 0 with MRI. I don't know of any problems serialising a BigDecimal though.

Contributor

tmornini commented Apr 26, 2012

Are those two examples from the same data set? If so, there's more than just the BigDecimal (which isn't a BigDecimal zero equivalent!) total_fees and total_price don't match, either!

Different data sets. I'm closing this issue for now until I can reproduce it outside of my app. Sorry for the inconvenience.

luckyruby closed this Apr 26, 2012

luckyruby reopened this Apr 26, 2012

Finally able to reproduce.

require 'bigdecimal'

class Utility
  def self.deep_copy(o)
    Marshal.load(Marshal.dump(o))
  end
end

foo = {}
for i in 0..10 do
  hash1 = { a: '1' }
  hash2 = { b: BigDecimal.new(100) }
  foo[i] = hash1.merge hash2
end

bar = Utility.deep_copy foo
puts bar

Error:
Backtrace:
Marshal.load at kernel/common/marshal.rb:1001
Utility.deep_copy at test2.rb:5
Object#script at test2.rb:16
Rubinius::CodeLoader#load_script at kernel/delta/codeloader.rb:67
Rubinius::CodeLoader.load_script at kernel/delta/codeloader.rb:109
Rubinius::Loader#script at kernel/loader.rb:632
Rubinius::Loader#main at kernel/loader.rb:836

Caused by: wrong constant name b (NameError)

Backtrace:
Rubinius::Type.coerce_to_constant_name at kernel/common/type.rb:109
Module(Class)#const_get at kernel/common/module19.rb:6
{ } in Marshal::State(Marshal::StringState)#const_lookup at
kernel/common/marshal.rb:267
Array#each at kernel/bootstrap/array.rb:68
Marshal::State(Marshal::StringState)#const_lookup at kernel/common
/marshal.rb:267
Marshal::State(Marshal::StringState)#construct_user_defined at
kernel/common/marshal.rb:625
Marshal::State(Marshal::StringState)#construct at kernel/common/marshal.rb:332
Marshal::State(Marshal::StringState)#construct at kernel/common/marshal.rb:372
{ } in Marshal::State(Marshal::StringState)#construct_hash at
kernel/common/marshal.rb:486
Integer(Fixnum)#times at kernel/common/integer.rb:87
Marshal::State(Marshal::StringState)#construct_hash at kernel/common
/marshal.rb:484
Marshal::State(Marshal::StringState)#construct at kernel/common/marshal.rb:324
{ } in Marshal::State(Marshal::StringState)#construct_hash at
kernel/common/marshal.rb:486
Integer(Fixnum)#times at kernel/common/integer.rb:87
Marshal::State(Marshal::StringState)#construct_hash at kernel/common
/marshal.rb:484
Marshal::State(Marshal::StringState)#construct at kernel/common/marshal.rb:324
Marshal.load at kernel/common/marshal.rb:999
Utility.deep_copy at test2.rb:5
Object#script at test2.rb:16
Rubinius::CodeLoader#load_script at kernel/delta/codeloader.rb:67
Rubinius::CodeLoader.load_script at kernel/delta/codeloader.rb:109
Rubinius::Loader#script at kernel/loader.rb:632
Rubinius::Loader#main at kernel/loader.rb:836

Member

ileitch commented Apr 26, 2012

I think BigDecimal is a red herring. Here is another example, note the dumped symbol for :b in the second Hash is now :E

foo = {0=>{:a=>"1", :b=>nil}, 1 => {:a=>"1", :b=>nil}}
Marshal.load(Marshal.dump(foo))
 => {0=>{:a=>"1", :b=>nil}, 1=>{:a=>"1", :E=>nil}} 

jfirebaugh closed this in ff4a674 May 1, 2012

@michalbugno michalbugno pushed a commit to michalbugno/rubinius that referenced this issue May 17, 2012

@jfirebaugh jfirebaugh + Michal Bugno Fix Marshal.dump for string encoding
The :E or :encoding symbol needs to be placed in the
symlink table like any other symbol.

Fixes #1681.
ca50e2e
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment