-1
class SimpleVariant
{
public:
    SimpleVariant()  { /*...*/ };
    // ...
};


struct VariantBlock
{
    int nRows, nCols;
    vector<SimpleVariant> theData;
};



void dumbFunction( VariantBlock& theBlock, int nRows, int nCols )
{
    // ...
    cout << "theBlock.nRows= " << theBlock.nRows 
         << ", theBlock.nCols= " << theBlock.nCols
         << ", theBlock.theData.size() " << theBlock.theData.size();

    theBlock.theData.resize( nRows * nCols );   
       // throws Access Violation Exception

    // ...
} 

Output returns that nRows=61, nCols=5, size()=0, which is exactly what it should be at that point, before an Access Violation Exception is thrown.

I'm using MSVC6, which is obviously not optimal, but there's no choice at this point.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Doug
  • 9
  • 1
  • What types of members do you have in `SimpleVariant`? Have you declared a copy constructor and/or copy assignment operator for `SimpleVariant`? If so, what do they do? There's nothing obviously wrong with the code you posted, though I have no recent experience with VC6. – James McNellis Mar 26 '11 at 05:18
  • 2
    This is probably bad copy behavior, as James has pointed out, but it also could be memory corruption elsewhere in the program. – templatetypedef Mar 26 '11 at 05:20
  • SimpleVariant consists of a bool, int, long and string and then an integer variable to specify type. – Doug Mar 26 '11 at 05:21
  • 2
    "Memory corruption elsewhere in the program" -- one thing that has me thinking that might be the case, is that originally, an exception seemed to be thrown elsewhere in the program. After putting in various "cout" debugging lines, the error seemed to move. – Doug Mar 26 '11 at 05:25
  • The "memory corruption elsewhere" could possibly be in a vector::insert, unless you have applied these bug fixes for the VC6 library: [http://www.dinkumware.com/vc_fixes.html](http://www.dinkumware.com/vc_fixes.html) – Bo Persson Mar 26 '11 at 05:42
  • @Bo: I never call insert() directly, is it called indirectly by resize()?? – Doug Mar 26 '11 at 05:48
  • 1
    Can you try the same thing in VS2008 or VS2010 Express just to prove that it's VC6 that's causing the problem? The VC6 STL implementation is well-known to be really bad. See http://stackoverflow.com/questions/191253 and http://epsilon-delta.net/articles/vc6_stl.html – Tim Sylvester Mar 26 '11 at 05:51
  • 1
    @Doug: You can verify yourself from the code, but documentation from one implementation suggests yes: "If sz is greater than the current vector size, the content is expanded by inserting at the end as many copies of c as needed to reach a size of sz elements. This may cause a reallocation." – Owen S. Mar 26 '11 at 05:52
  • @Doug - I don't know exactly what VC6 does here (have upgradred 5 times since that :-). Just remembered the magic term to google for. – Bo Persson Mar 26 '11 at 05:57
  • I should clarify one thing. This function USED to work. The program is full of std::vectors. While it might be a VC6 issue, and I would love to change, I don't believe it's the issue. – Doug Mar 26 '11 at 05:58
  • 1
    This kind of bug requires a tool like http://valgrind.org – Chris Dodd Mar 26 '11 at 06:47

3 Answers3

2

I recently had to upgrade some code that was originally written for Visual C++ 6. That code had trouble in that VC++ 6 did not handle what could bind to a reference correctly. This is something of a shot in the dark, but are you passing in a const VariantBlock to dumbFunction? Under C++ rules, that would be illegal, but I strongly suspect that VC++ 6 would get that wrong.

Another possibility would be some kind of runtime mismatch. If (1) the VariantBlock is allocated in one module and (2) dumbFunction is from a different module, and (3) they were compiled with different settings, possibly different versions of the compiler, then you will see this kind of behavior (the resize() allocates new memory, copies everything over to it, and then goes to deallocate the old memory, except the old memory was allocated in a different runtime, so the program barfs).

In short, the code you posted is perfectly fine. There's something else going on.

Max Lybbert
  • 19,717
  • 4
  • 46
  • 69
1

I think you did something wrong before that error. An std::vector::resize operation is going to ask for memory and the heap is an easy victim for corruption. The bad thing about undefined behavior is that the symptoms can become visible one million executed instructions after the error (i.e. "anything can happen" includes "nothing").

We have a "debug memory manager" that redefines the global allocator and that can do a lot of checks for corruption:

  1. Initializes allocated memory with a non obvious bit pattern (this is to spot problems when someone uses uninitialized memory and apparently code works when finds zeroes)
  2. Adds some "safety area" before and after every memory block and check on deletion that it has not been overwritten (this is for buffer overrun detection)
  3. Fills memory with a different specific pattern on deallocation (this is to try to catch read-after-delete errors)
  4. Reuses memory blocks and on reallocation or on global verify checks that the deleted memory pattern is still there (this is to catch write-after-delete errors)
  5. Marks every block with __FILE__/__LINE__ information to detect who is leaking memory leaks and to be able to tell who was using the block that got corrupted after deletion.

also we have a memory check routine that on demand can walk all the memory blocks and check for consistency (normally we do checks only on allocation/deallocation). We can also just log out a complete list of all allocations/deallocations of memory for desperate cases.

Unfortunately for point (5) C++ syntax is hard to instrument so we actually don't use new but an xnew macro that eventually expands into a placement allocation; this also means that we cannot instrument memory blocks allocated inside the standard library (we store however what was the last source line that did an allocation inside our program before the allocation in the library occurred).

6502
  • 112,025
  • 15
  • 165
  • 265
1

I am the OP.

The problem was memory corruption from the calling functions.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
user677925
  • 11
  • 1