From: Robert Klemme Date: 2008-05-23T18:30:07+09:00 Subject: Re: customized serialization unreliable???? On 23.05.2008 02:29, Stefan Rusterholz wrote: > sayoyo Sayoyo wrote: >> Hi, >> >> I have a strange problem with the customized serialization... >> I have a large object which is built by several classes and each class >> has its own marshal_dump and marshal_load, like: >> >> class YYY >> attr_reader :data, :version >> >> def initialize >> @data = "different objects" >> @version = 1 >> end >> >> def marshal_dump() >> return [@version,@data] >> end > > Your problems most likely are caused by you returning an array instead > of a String. I'm surprised Marshal doesn't complain. I don't think a String must be returned? Apparently the standard lib also does not think so: irb(main):009:0> require 'ostruct' => true irb(main):010:0> o=OpenStruct.new => # irb(main):011:0> o.foo=123 => 123 irb(main):012:0> o.marshal_dump => {:foo=>123} irb(main):013:0> o.marshal_dump.class => Hash irb(main):014:0> > class Foo > def marshal_dump > Marshal.dump([@version, @data]) > end > def marshal_load(data) > @version, @data = *Marshal.load(data) > end > ... > end > > This works here quite well without any random outtakes. At least I > haven't yet hit one. I'll show you one - but it's not random. :-) Your approach with the String works only well for simple cases. But the downside is that it does not handle loops in object graphs properly: robert@fussel /cygdrive/c/Temp $ cat marsh.rb F = Struct.new :x, :y a = F.new b = F.new c = F.new a,b a.x = c b.x = c t1 = Marshal.load(Marshal.dump(c)) p t1.equal?(t1.x.x) class F def marshal_dump [x,y] end def marshal_load(dat) self.x, self.y = dat end end t2 = Marshal.load(Marshal.dump(c)) robert@fussel /cygdrive/c/Temp $ cat marsh.rb F = Struct.new :x, :y a = F.new b = F.new c = F.new a,b a.x = c b.x = c t1 = Marshal.load(Marshal.dump(c)) p t1.equal?(t1.x.x) class F def marshal_dump [x,y] end def marshal_load(dat) self.x, self.y = dat end end t2 = Marshal.load(Marshal.dump(c)) p t2.equal?(t2.x.x) class F def marshal_dump Marshal.dump([x,y]) end def marshal_load(dat) self.x, self.y = Marshal.load(dat) end end t3 = Marshal.load(Marshal.dump(c)) p t3.equal?(t3.x.x) robert@fussel /cygdrive/c/Temp $ ruby marsh.rb true true marsh.rb:26:in `marshal_dump': stack level too deep (SystemStackError) from marsh.rb:26:in `dump' from marsh.rb:26:in `marshal_dump' from marsh.rb:26:in `dump' from marsh.rb:26:in `marshal_dump' from marsh.rb:26:in `dump' from marsh.rb:26:in `marshal_dump' from marsh.rb:26:in `dump' from marsh.rb:26:in `marshal_dump' ... 15600 levels... from marsh.rb:26:in `dump' from marsh.rb:26:in `marshal_dump' from marsh.rb:34:in `dump' from marsh.rb:34 robert@fussel /cygdrive/c/Temp $ Kind regards robert