views:

622

answers:

2

This is on Visual Studio 2008 on a dual-core, 32 bit Vista machine. In the debug code this runs fine, but in Release mode this bombs:

void getFromDB(vector<string>& dates) {
    ...
    sql::Resultset res = stmt->executeQuery("SELECT FROM ...");
    while (res->next()) {
       string date = res->getString("date");
       dates.push_back(date);
    }   // <<< crashing here (line 56)
    delete res;
}

The MySQL C++ connector has this method in it's ResultSet:

virtual std::string getString(const std::string& columnLabel) const = 0;

For some reason in the release compiled (against a MySQL C++ connector DLL) this crashes at the end of the loop with a heap corruption:

HEAP[sa-ms-release.exe]: Invalid address specified to RtlFreeHeap( 024E0000, 001C4280 ) Windows has triggered a breakpoint in sa-ms-release.exe.

    ntdll.dll!_RtlpBreakPointHeap@4()  + 0x28 bytes 
    ntdll.dll!_RtlpValidateHeapEntry@12()  + 0x713e8 bytes 
    ntdll.dll!_RtlDebugFreeHeap@12()  + 0x9a bytes 
    ntdll.dll!@RtlpFreeHeap@16()  + 0x145cf bytes 
    ntdll.dll!_RtlFreeHeap@12()  + 0xed5 bytes 
    kernel32.dll!_HeapFree@12()  + 0x14 bytes 
>   sa-ms-release.exe!free(void * pBlock=0x001c4280)  Line 110 C
    sa-ms-release.exe!std::allocator<char>::deallocate(char * _Ptr=0x001c4280, unsigned int __formal=32)  Line 140 + 0x9 bytes C++
    sa-ms-release.exe!std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Tidy(bool _Built=true, unsigned int _Newsize=0)  Line 2158 C++
    sa-ms-release.exe!std::basic_string<char,std::char_traits<char>,std::allocator<char> >::~basic_string<char,std::char_traits<char>,std::allocator<char> >()  Line 907 C++
    sa-ms-release.exe!StyleData:: getFromDB( std::vector<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::allocator<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > > & dates)  Line 56 + 0x69 bytes C++

I think I may be violating some basic C++ rule that causes the destructor to be called on a string I want to preserve inside the vector.

If I replace

string date = res->getString("date")

with

string date = string ("2008-11-23");

everything works fine. It seems to have to do with the string returned from the MySQL C++ Connector getString() method. The returned string is destroyed and that causes the problem, I guess. But more likely something else is wrong. I am using the release (opt) MySQL connector.

+2  A: 

imho, problem may arise from VS run time libraries.That means, DLL you use for sql connector methods are compiled not with "multi thread dll" code generation option.So different versions of strings are passed through parameters and they chrash.I think you should check this code generation flag.

Qubeuc
Yeah. I too guess that will be the reason. Perhaps /MD or /MDd ? If i remember correctly. If these are there in DEBUG mode options, then definitely that's the reason
Aviator
The MySQl Connector is compiled with /MD and my code with /MT. Now both are /MD. Code now works!!! Thanks
Martin Stein
+1  A: 

You can have a look at this thread

Even though the problem is reported on XP, the situation is same. The reason being "string getting destroyed on different heap rather than the one it was created on."

In your case, the string gets allocated at the Connector DLL heap which was getting freed in Application heap.

I guess you can find some good suggestions over that thread. (Compiling both DLL and APP using same runtime, or passing string by reference between application and dll calls)

Aviator
The reason was two conflicting runtime libraries specified. I think this is quite complex. Do the two DLLs have to have separate heaps? Is this the same under Unix/Linux? Java is so much easier.
Martin Stein
I dont think this is same under Linux...Yeah :).. I too feel java is easier in these cases, by abstracting all lower level details... But there might be specific reasons why they designed it that way! I can never understand that much complex reasoning logic behind these decisions!! :)
Aviator