I have an object with the following method:
int PathSubstitution::updateField(Field4memo &field, int record_id, int field_id) const
{
    int type = field.type();
    if((type == r4str) || (type == r4memo) || (type == r4unicode))
    {
        string value = field.str();
        trim(value);
        if(!substituteDriveLetters(value))
            return -1;
        if(!substituteGridMount(value))
            return -1;
        return field.assign(value.c_str(), value.length());
    }
    return r4success;
}
When I build this code with my Debug profile in Visual Studio C++ 2010 everything works just fine. This method gets called 4 times, on four unique Field4memo objects, and it works.
When I build this code with my Release profile the method works the first time it's called, but causes Vista Enterprise to display a "program.exe has stopped working" dialog window. The "View problem details" area of the window says:
Problem signature:
  Problem Event Name:   BEX
  Application Name: program.exe
  Application Version:  0.0.0.0
  Application Timestamp:    4ef4edc6
  Fault Module Name:    program.exe
  Fault Module Version: 0.0.0.0
  Fault Module Timestamp:   4ef4edc6
  Exception Offset: 0000668a
  Exception Code:   c0000409
  Exception Data:   00000000
  OS Version:   6.0.6002.2.2.0.256.4
  Locale ID:    1033
  Additional Information 1: 6243
  Additional Information 2: 0d5daf38e26c963685a835e6f40ff03d
  Additional Information 3: aa53
  Additional Information 4: 5d02a603659cce53ff840117c3a9c7a7
The BEX event name indicates a buffer overflow. But which buffer, I cannot tell.
Here's where it gets weird for me though...
When I change this method and add an unnecessary cout line to it, it works with the Release profile:
int PathSubstitution::updateField(Field4memo &field, int record_id, int field_id) const
{
    int type = field.type();
    if((type == r4str) || (type == r4memo) || (type == r4unicode))
    {
        // THIS IS THE NEW LINE I ADDED RIGHT BELOW HERE!!!
        cout << endl;
        string value = field.str();
        trim(value);
        if(!substituteDriveLetters(value))
            return -1;
        if(!substituteGridMount(value))
            return -1;
        return field.assign(value.c_str(), value.length());
    }
    return r4success;
}
I can't tell why the method crashes with the Release profile or why adding the cout line resolves the crashing issue. I'm uncomfortable just accepting the "cout fixes it" answer -- can someone help me understand what my problem is here and why the cout fixes it? How does the cout call save me from a buffer overflow here?
Edit: some additional context for the call to this method was asked for. It's called in a loop. With the test input I'm using, it's called 4 times. The function that calls it looks like so:
int PathSubstitution::updateRecord(Data4 &dbf, int record_id) const
{
    // Update all fields
    int numFields = dbf.numFields();
    for(int i = 1; i <= numFields; i++ )
    {          
        Field4memo field(dbf, i);
        int rc = updateField(field, record_id, i);
        if(rc != r4success)
            return rc;
    }
    return r4success;
}
Edit 2: Flushing the cout buffer also fixes the overflow problem as long as cout.flush() is called from within the PathSubstitution::updateField method and before the return field.assign(value.c_str(), value.length()); line.
Edit 3: This is promising. If I comment out the calls the substituteDriveLetters() and substituteGridMount() methods the program doesn't crash. So it's something to do with those method calls (which use pcre to do some regular expression string substitutions).
Edit 4: If I comment out just the substituteDriveLetters() method it works. So I've got a prime suspect now. This method is supposed to replace a drive letter in a path with the corresponding UNC value. None of the fields in my test input are file paths so this should be a null op as far as data transformation is concerned.
bool PathSubstitution::substituteDriveLetters(string &str, string::size_type offset) const
{
    int offsets[6];
    int groups = pcre_exec(drivePattern, NULL, str.c_str(), str.size(), 0, 0, offsets, sizeof(offsets));
    if(groups < 0)
    {
        switch(groups)
        {
        case PCRE_ERROR_NOMATCH:
        case PCRE_ERROR_PARTIAL:
            return true;
        case PCRE_ERROR_NOMEMORY:
            cerr << "WARNING: Out of memory." << endl;
            break;
        case PCRE_ERROR_BADUTF8:
        case PCRE_ERROR_BADUTF8_OFFSET:
            cerr << "WARNING: Bad UNICODE string." << endl;
            break;
        default:
            cerr << "WARNING: Unable to substitute drive letters (Err: " << groups << ")" << endl;
            break;
        }
        return false;
    }
    char driveLetter = toupper(str[offsets[2]]);
    DriveMap::const_iterator i = driveMap.find(driveLetter);
    if(i == driveMap.end())
    {
        cerr << "ERROR: The " << driveLetter << " drive is not mapped to a network share." << endl;
        return false;
    }
    string::iterator start = str.begin() + offsets[0];
    string::iterator end = str.begin() + offsets[1];
    str.replace(start, end, i->second);
    return substituteDriveLetters(str, offsets[1]);
}
 
    