1

I'm using protobuf-net lib with protobuf-net memcache provider and I'm trying to use memcache append function:

var data = new ArraySegment<byte>(Encoding.UTF8.GetBytes("appendedString"));
var result = _memcache.ExecuteStore(StoreMode.Add, key, data);

And it throws exception:

The runtime has encountered a fatal error. The address of the error was at 0x63765a43, on thread 0xd58. The error code is 0xc0000005. This error may be a bug in the CLR or in the unsafe or non-verifiable portions of user code. Common sources of this bug include user marshaling errors for COM-interop or PInvoke, which may corrupt the stack.

I've done some debug and find out place when that exception is raised:

/Meta/RuntimeTypeModel.cs: 692: ((MetaType)types[key]).Serializer.Write(value, dest);

Here value is that ArraySegment which I want to set as value and dest is ProtoBuf.ProtoWriter.

Is there any way to fix that error or, maybe, I'm doing something wrong. Maybe I just simply need to store not an ArraySegment, but just string and append strings to it too?

m03geek
  • 2,508
  • 1
  • 21
  • 41
  • Here's a question for you: if someone sends an `ArraySegment` with an `Array` of length `300`, an `Offset` of `20`, and a `Count` of `3`... would you expect all 300 to be serialized? or just the 3? And if the 3 - would you expect the deserialized array to be 300 long with `Offset` of `20` and `Count` of `3` (and the rest blank), or would you expect it to be an array of length 3, with `Offset` of `0` and `Count` of `3` ? – Marc Gravell May 30 '13 at 19:23
  • Difficult question. On the one side to reduce communication cost it's better to serialize only 3. On the other side I'll expect to deserialize same object I've serialized, with 300 `length`, etc. I don't know how other protobuf serializers work, but protobuf is used not only for making serialization cross-language and cross-platform but to reduce serialized object size. So great variant is in array with `length` 300 to serialize only that `count` 3 and may be some additional 4th element says that rest 277 elements are empty and deserialize array with 300 length. – m03geek May 30 '13 at 20:57
  • If that is not possible then I prefer the variant that serializes just 3 and deserializes it to array length of 3. May be this way is wrong, but it makes less serialized object size, so if I have 1 million of such arrays I could spend less bandwidth (or disk space) to transmit or save them. – m03geek May 30 '13 at 21:04
  • By the way it's good question for asking stackoverflow community. May be someone have better idea. – m03geek May 30 '13 at 21:20
  • I suspect the only sane answer is "return the shortest array possible" - so 0 offset, length 3. Just wondered your thoughts, since you brought up the issue of array segment – Marc Gravell May 30 '13 at 21:26

1 Answers1

2

Heh; in all honesty I've never tested ArraySegment<T> - despite the intentions of the CLR team, it simply isn't used all that much. I can reproduce this in a very simple test:

using ProtoBuf;
using System;
[ProtoContract]
class Foo
{
    [ProtoMember(1)]
    public ArraySegment<byte> Data { get; set; }
    static void Main()
    {
        var obj = new Foo { Data = new ArraySegment<byte>(new byte[] { 1, 2, 3 })};
        Serializer.PrepareSerializer<Foo>();
        var clone = Serializer.DeepClone(obj);
    }
}

which I will add to the test suite, and fix.

For now, may I suggest: just store the byte[]... (i.e. don't use ArraySegment<T>). This will probably be fixed in the next build of protobuf-net.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • I've used ArraySegment because of _memcache.ExecuteAppend needs that and thought that I need to store initial string value also as ArraySegment. Now I've changed store to simple string, not ArraySegment and it seems working without exceptions. But if someone need to store ArraySegment he'll catch that exception. – m03geek May 30 '13 at 14:15
  • @Alex indeed; and I'll try to fix that for the next build – Marc Gravell May 30 '13 at 14:17