Blog

Beware File Open/Save Dialogs: They May Change The Current Directory
Win32 c mfc win32
Published: 2005-09-08
Beware File Open/Save Dialogs: They May Change The Current Directory

On some Windows operating systems (primarily Windows 95, 98, and ME), GetOpenFileName() and GetSaveFileName() (and wrappers of these functions such as MFC’s CFileDialog) will permanently change the process’s current working directory unless the OFN_NOCHANGEDIR option is specified. As you can imagine, this can easily break your application if you ever rely on the current working directory being set to a particular value (such as if you open files using relative paths).

Of course, it is best to eliminate any such current working directory assumptions from your application completely.

Read more...
Be Careful With Bitfields
C++ c win32
Published: 2005-09-07
Be Careful With Bitfields

Consider the following piece of code (adapted from a real-world bug):

1
2
3
4
5
6
7
BOOL IsDirectory(LPCTSTR strPathName)
{
    DWORD dwAtts = GetFileAttributes(strPathName);
    if (dwAtts == INVALID_FILE_ATTRIBUTES)
        return FALSE;
    return (dwAtts == FILE_ATTRIBUTE_DIRECTORY);
}

This function will work most of the time, but every now and again it will run across a directory which it will claim isn’t one. Why?

Read more...
Use Constant References For Input-Only Parameters, Pointers Otherwise
C++ c++
Published: 2005-09-06
Use Constant References For Input-Only Parameters, Pointers Otherwise

This is a style issue, so there is no right or wrong, but I suggest using a const reference for an input-only paramater to a C++ function and a pointer for an input/output or output-only parameter. This makes it slightly more obvious that the parameter might be modified by the function.

Example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
ReturnType Function
    (
    const ParamType& inputParam,
    ParamType* inputOutputParam,
    ParamType* outputParam
    )
{
    // ...
}

void User()
{
    ParamType inputParam;
    ParamType inputOutputParam;
    ParamType outputParam;

    // Note the &s -- this is a bit of a warning something
    // might happen to inputOutputParam or outputParam...
    ReturnType ret = Function
        (
        inputParam,
        &inputOutputParam,
        &outputParam
        );
}
Write Functions Which Take Iterators, Not Collections
C++ c++ stl
Published: 2005-09-05
Write Functions Which Take Iterators, Not Collections

If my experience is typical, this is a very common construct:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
ReturnType Function
    (
    const std::vector<T>& container
    )
{
    typedef std::vector<T>::const_iterator iterator_t;
    for (iterator_t iter = container.begin();
         iter != container.end();
         ++iter)
    {
        // Work with *iter
    }
}

The problem with this construct is that you have forced a container choice upon the user of your function. Slightly better, and basically your only choice when interoping with C, is this:

Read more...
Prefer Iteration To Indexing
C++ c++ stl
Published: 2005-09-02
Prefer Iteration To Indexing

I’ve seen the following STL construct countless times:

1
2
3
4
std::vector<T> container;
for (int i = 0; i < container.size(); ++i) {
    // Work with container[i]
}

Unless otherwise necessary, it is better to use an STL iterator because it enables you to more easily change the underlying container. You can isolate the code changes required to one line by using typedef, as in:

Read more...
Revisiting Excel Interop
Excel Interop csharp excel interop
Published: 2005-08-24
Revisiting Excel Interop

I ran into problem today relating to Excel interop. A coworker made a change to a C# application I wrote and was trying to build it. The program relied on a project which had a reference to the Microsoft Excel 9.0 Object Library which ships with Office 2000. However, the coworker had Office 2003 installed which includes the Excel 11.0 Object Library and not the Excel 9.0 Object Library. Because of this, he could not build the application.

Read more...
Deterministic Finalization and IDisposable Part 5: Useful IDisposable Class 3: AutoReleaseComObject
Deterministic Finalization and IDisposable csharp excel interop
Published: 2005-02-15
Deterministic Finalization and IDisposable Part 5: Useful IDisposable Class 3: AutoReleaseComObject

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

This is the final example in my series on deterministic finalization in garbage-collected languages and the true motive behind the series: AutoReleaseComObject. The idea behind AutoReleaseComObject is simple: it is nothing but a wrapper around a COM object which calls Marshal.ReleaseComObject() upon Dispose() until the COM object’s reference count is 0 and the object is freed. Here’s the implementation:

Read more...
Deterministic Finalization and IDisposable Part 4: Useful IDisposable Class 2: AutoDeleteFile
Deterministic Finalization and IDisposable csharp
Published: 2005-02-14
Deterministic Finalization and IDisposable Part 4: Useful IDisposable Class 2: AutoDeleteFile

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

I guess my definition of tomorrow is much longer than I thought, but here’s another useful IDisposable class which I shall present without comment: AutoDeleteFile.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
using System;
using System.Diagnostics;
using System.IO;

/// <summary>
/// A file wrapper which automatically deletes the file unless Disarm()
/// is called.
/// </summary>
public sealed class AutoDeleteFile : IDisposable
{
    private FileInfo m_underlyingFile;
    private bool m_armed = true;
    private bool m_disposed = false;

    public AutoDeleteFile(FileInfo underlyingFile)
    {
        Debug.Assert(underlyingFile != null);
        m_underlyingFile = underlyingFile;
    }

    ~AutoDeleteFile()
    {
        Dispose(false);
    }

    public FileInfo File
    {
        get { return m_underlyingFile; }
    }

    public void Disarm()
    {
        m_armed = false;
    }

#region IDisposable Members
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
#endregion

    private void Dispose(bool disposing)
    {
        if (!m_disposed)
        {
            if (m_armed)
            {
                try
                {
                    m_underlyingFile.Delete();
                }
                catch (Exception)
                {
                    // If we can't delete, oh well!
                }
            }

            m_disposed = true;
        }
    }
}
Deterministic Finalization and IDisposable Part 3: Useful IDisposable Class 1: TimedLock
Deterministic Finalization and IDisposable csharp
Published: 2005-02-13
Deterministic Finalization and IDisposable Part 3: Useful IDisposable Class 1: TimedLock

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

For the first example of a useful custom class which implements IDisposable, I will simply link to and reproduce Ian Griffith’s TimedLock — an enhancement of the C# lock statement which allows the specification of a timeout period instead of blocking forever while trying to obtain the lock.

The code for TimedLock is reproduced below:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
using System;
using System.Threading;

// Thanks to Eric Gunnerson for recommending this be a struct rather
// than a class -- avoids a heap allocation.
// Thanks to Change Gillespie and Jocelyn Coulmance for pointing out
// the bugs that then crept in when I changed it to use struct...
// Thanks to John Sands for providing the necessary incentive to make
// me invent a way of using a struct in both release and debug builds
// without losing the debug leak tracking.
public struct TimedLock : IDisposable
{
    public static TimedLock Lock (object o)
    {
        return Lock (o, TimeSpan.FromSeconds (10));
    }

    public static TimedLock Lock (object o, TimeSpan timeout)
    {
        TimedLock tl = new TimedLock (o);
        if (!Monitor.TryEnter (o, timeout))
        {
#if DEBUG
            System.GC.SuppressFinalize(tl.leakDetector);
#endif
            throw new LockTimeoutException ();
        }
        return tl;
    }

    private TimedLock (object o)
    {
        target = o;
#if DEBUG
        leakDetector = new Sentinel();
#endif
    }

    private object target;

    public void Dispose ()
    {
        Monitor.Exit (target);
        // It's a bad error if someone forgets to call Dispose,
        // so in Debug builds, we put a finalizer in to detect
        // the error. If Dispose is called, we suppress the
        // finalizer.
#if DEBUG
        GC.SuppressFinalize(leakDetector);
#endif
    }

#if DEBUG
    // (In Debug mode, we make it a class so that we can add a finalizer
    // in order to detect when the object is not freed.)
    private class Sentinel
    {
        ~Sentinel()
        {
            // If this finalizer runs, someone somewhere failed to
            // call Dispose, which means we've failed to leave
            // a monitor!
            System.Diagnostics.Debug.Fail("Undisposed lock");
        }
    }

    private Sentinel leakDetector;
#endif
}

public class LockTimeoutException : ApplicationException
{
    public LockTimeoutException () : base("Timeout waiting for lock")
    {
    }
}

It is trivial to use TimedLock instead of lock in your applications. Simply change statements from:

Read more...