0

I have issues satisfying a code analysis rule for disposing a MemoryStream object.

This is my code right now:

byte[] bytes;
MemoryStream stream = new MemoryStream();

using (CryptoStream cs = new CryptoStream(stream, transform, CryptoStreamMode.Write))
{
    cs.Write(buffer, 0, buffer.Length);
}

bytes = stream.ToArray();
stream.Close();

return bytes;

This results in a warnings that the stream may be disposed twice, or may not be disposed (one warning for each).

I have also tried wrapping it into a using(MemoryStream stream = new MemoryStream()) block. This results in the former warning.

And finally, removing the calls to Close() or Dispose() results in the latter warning.

Is there a way to satisfy both conditions? I assume the problem is an exception path that may close it, but I am not very familiar with how these classes work.

Blorgbeard
  • 101,031
  • 48
  • 228
  • 272
Alexandre
  • 5
  • 6

3 Answers3

2

You can throw out all the streams by using

var bytes = transform.TransformFinalBlock(buffer, 0, buffer.Length);

If there are no streams, you don't need worry about disposing them ;)

CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
  • Real solution to the problem at hand (also question itself is duplicate of exactly the same sample http://stackoverflow.com/questions/3831676/ca2202-how-to-solve-this-case ) – Alexei Levenkov Dec 16 '14 at 21:34
1

I personally tend to suppress that rule in my source code if it fires because most objects do not have a problem being disposed twice. But if you want to satisfy the Rule without suppressing you need to do this:

        byte[] bytes = new byte[1024];
        byte[] buffer = new byte[1024];
        ICryptoTransform transform = null;

        MemoryStream stream = null;

        try
        {
            stream = new MemoryStream();
            MemoryStream tempStream = stream

            using (CryptoStream cs = new CryptoStream(stream, transform, CryptoStreamMode.Write))
            {
                // set stream to null immediately so it doesn't get disposed by finally
                stream = null;

                cs.Write(buffer, 0, buffer.Length);
                bytes = tempStream.ToArray();
            }
        }
        finally
        {
            if (stream != null)
            {
                stream.Dispose();
            }
        }

        return bytes;
Mike Burdick
  • 838
  • 6
  • 5
0

When CryptoStream is disposed (when the using block ends), it calls Close on the MemoryStream, which calls Dispose.

So, you don't need to call Dispose (via using) or Close yourself. This way, stream only gets disposed exactly once.

MemoryStream stream = new MemoryStream();
using (CryptoStream cs = new CryptoStream(stream, transform, CryptoStreamMode.Write))
{
    cs.Write(buffer, 0, buffer.Length);
    return stream.ToArray();            
}
Blorgbeard
  • 101,031
  • 48
  • 228
  • 272
  • That code can leave the MemoryStream undisposed if the CryptoStream constructor throws. – Mike Burdick Dec 16 '14 at 21:20
  • True, but it's not (IMO) a big deal. An empty MemoryStream is not large, and will still be GC'd eventually. And hopefully it is unlikely that CryptoStream's ctor throws. I don't see a way around it without triggering one of the code-analysis warnings. – Blorgbeard Dec 16 '14 at 21:23
  • I tend to suppress this rule and use 2 using statements. But if you want not suppress and always dispose I updated my answer with the try/finally block to satisfy the rule. – Mike Burdick Dec 16 '14 at 21:28
  • @Blorgbeard `MemoryStream` have no-op `Dispose` by design since it has to keep internal buffer (managed byte array) alive for later calls to `ToArray`. So even not disposing "huge `MemoryStream`" is not an issue (nice to have correctly looking code, but no real difference). – Alexei Levenkov Dec 16 '14 at 21:28