Blog

Deterministic Finalization and IDisposable Part 1: The Basics
Deterministic Finalization and IDisposable csharp garbage collection
Published: 2005-02-11
Deterministic Finalization and IDisposable Part 1: The Basics

This is part 1/5 of my Deterministic Finalization and IDisposable post series.

This topic has been covered many times by many others (such as here and here), so if you are familiar with C#’s using statement and IDisposable interface, feel free to skip this post. I’m writing this introduction to provide the necessary background information to set up a series of subsequent posts.

Garbage collection, found in languages such as C# and Java (among many others), is a very useful feature: it largely alleviates the need for a programmer to manually handle resource management. The most commonly cited benefit is that garbage collection eliminates the need for the programmer to explicitly call heap memory management functions such as malloc and free; instead, the garbage collector automatically keeps track of whether objects are still in use and frees them when they are no longer needed.1 However, in addition to handling memory management, garbage collection may also release other scarce resources upon cleanup, such as file locks or network connections.

Read more...
In-Memory Decompression of gzip using Zlib
Compression c gzip zlib
Published: 2004-09-01
In-Memory Decompression of gzip using Zlib

At work I recently was given the task to support gzip-based HTTP response compression in a C++ MFC application. For a while I was convinced that there was no way to support in-memory decompression of gzip-compressed data using zlib, and so I wrote the gzipped data to a temporary file and then used the gzopen()/gzread()-family of functions in zlib to read it back (as described in the zlib manual).

I spent a lot of time looking at the zlib code to try to see why the in-memory streaming decompression function inflate() wasn’t working for gzip-compressed data and determined that zlib wasn’t recognizing the gzip headers. The inflate() function had code which purported to understand the headers, but it wasn’t being enabled due to reasons unknown. After some more sleuthing, I noticed the gzopen()/gzread() functions implemented their own gzip header detection and passed only the raw data to inflate(). Once I noticed this, I threw my hands up in disgust and said it couldn’t be done.

Read more...
Using the Excel Object Model and Performance
Excel Interop c++ excel interop mfc
Published: 2004-07-20
Using the Excel Object Model and Performance

Recently I’ve had to write a bit of code which communicates with Microsoft Excel using its object model. Here are a few things I have learned from this experience.

1
2
3
4
Excel::_Application app;
// Create and work with app...
app.SetVisible(true);
app.SetUserControl(true);
  • Even if Excel is not visible to the user, Application::Quit() may pop up a hidden dialog asking if the user wants to save the changes that were made through the dialog box. Since the dialog is not visible, Excel will never shut down. To prevent this dialog, either set Application.DisplayAlerts to false or set Workbook.Saved to true for all modified workbooks. The former is preferred.
  • Each call using the Excel object model is very, very slow, probably as a result of the use of IPC. This means that the typical way one would think of interacting with cell values in Excel — iterating cell-by-cell within a set of nested for loops — is often too slow to be practical. Instead, I work in selections of nRows rows by nCols columns and use a two-dimensional SAFEARRAY. For example:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
COleSafeArray rawData;
DWORD rawDataDimensions[2];
rawDataDimensions[0] = nRows;
rawDataDimensions[1] = nCols;
rawData.Create(VT_VARIANT, 2, rawDataDimensions);
// Populate the values of rawData...
// Select a range of size nRows x nCols
Excel::Range range = wksheet.GetRange(varUpperLeftCell, varLowerRightCell);
// Set the cells' values in one call to .SetValue()
// instead of setting individual cell values
range.SetValue(rawData);