Problems when destroying a vector of strings

I have 2 vectors of strings. I'm passing them to a function by reference with one being const inside the function. I add some strings to the non-const vector and come out of the function. For some reason when the vector that was not const goes out of scope it throws exceptions when trying to deallocate the strings. Here is an example.

//it doesn't matter what happens to vector1 because it is working properly
//disregard it for this example
vector2.clear(); //to make sure it's empty
//push on some random data for this example
//I'm actually grabbing some text from an access DB
for (int i = 0; i < 8; i++)
{

vector2.push_back("Go Time!");

}

}
int main()
{

vector<string> vector1;
vector<string> vector2;
func1(vector1, vector2);
//do something with vector 2 now, only reading from it though, no writing
//I was letting them go out of scope but I couldn't tell which vector was having trouble
//The problem manifests when clear() is called as well
vector1. clear();
vector2.clear(); //here is where the program breaks
return 1;

}

It doesn't seem matter what text is in the vector. I've tried rearranging the order of the string but it always seems to break on the second or third element. I've tried doing a pop_back() from the end of the vector and it goes fine until it gets up toward the beginning of the vector.

Just for reference I'm using Visual C++ 6.0 (ugh) and vector1 destroys just fine. The actual exception is happening when in the std::string's deallocate function. It is throwing an assert on IsValidHeapPointer.

Thanks in advance for any help.

Last edited by ryanrigdon; 08-14-2009 at 09:25 AM.
Reason: Just to remove a typo/programmer error

Or does this exact example have the problem (if it runs fine why did you post it?)

I posted this as an example of the operations I am performing on the vectors without bogging you down on the details. All I am doing is pushing some strings into the vector in func1 then reading them back from it after the func1 call.

vector2 is never modified after coming out of func1.

the exception always occurs when trying to deallocate the strings in vector2, whether by calling clear(), the vector going out of scope, or individually popping off each string.

The only thing I forgot to mention is that in my code, func1 is in a dll. Could Is there any special consideration I'm not managing in regards to modifying a vector across a dll?

>> Could Is there any special consideration I'm not managing in regards to modifying a vector across a dll?

Make sure all your allocations and deallocations are done in the same module (see C++ Coding Standards item 60). I don't know if that's your problem, but I do know that there can be problems if you create your vector in one place and fill it in the dll. Something tells me this isn't your problem, but it's worth a shot to reserve space for the vector before sending it to the function. There still could be a problem with the string, though.

Memory allocated in the DLL's heap is distinct from the executable's heap. This means that when you create memory inside the dll it must also be deleted inside the dll.

This is especially a problem in your case as there's a lot of stuff going on inside the string constructor and it's highly likely that it's creating local pointers when you push to the vector in the dll and therefore errors out when you release that memory inside your main program.

//it doesn't matter what happens to vector1 because it is working properly
//disregard it for this example
//assign new values to the initialized strings
for (int i = 0; i < 8; i++)
{

vector2[i] = "Go Time!";

}

}
int main()
{

vector<string> vector1;
vector<string> vector2(20, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
func1(vector1, vector2);
//I was letting them go out of scope but I couldn't tell which vector was having trouble
//The problem manifests when clear() is called as well
vector1. clear();
vector2.clear(); //here is where the program breaks
return 1;

}

Even though I'm not allocating anything in the dll and not doing anything with the vector after getting it back I'm still getting an assert from IsValidHeapPointer in std::string's destructor. But if I take out the call to func1 it works just fine.

Heap stomping. The problem lies in the code you think is not relevant.

Yep, nice choice of words there. =)

>> Even though I'm not allocating anything in the dll and not doing anything with the vector after getting it back I'm still getting an assert from IsValidHeapPointer in std::string's destructor. But if I take out the call to func1 it works just fine.

Well, in the code you posted you aren't checking the bounds of vector - try constraining it to vector2.size( ) and recheck.

I'm not sure where you mean for me to check the bounds unless it is in the "for" loop in func1. Unfortunately, checking the bounds isn't going to help because the error occurs in clear() which requires no bounds checking. I have even tried

Code:

for (int i = 0; i < vector2.size(); i++)
{

vector2.pop_back();

}

This makes it all the way up to the second or third element and then breaks with the same error.

I'm not sure where you mean for me to check the bounds unless it is in the "for" loop in func1. Unfortunately, checking the bounds isn't going to help because the error occurs in clear() which requires no bounds checking. I have even tried

Code:

for (int i = 0; i < vector2.size(); i++)
{

vector2.pop_back();

}

This makes it all the way up to the second or third element and then breaks with the same error.

I posted this as an example of the operations I am performing on the vectors without bogging you down on the details.

Sadly, the only thing that is going to be of use for us to help solve the problem is the details.
Otherwise it's like finding a picture of a car engine on the net to post on a forum and say, "see my car has broken down".

My advice is that where a call to a different module is involved (e.g. EXE to DLL) DO NOT pass or return standard library structures of any kind. Maybe you will get away with it if it is const and both are built using the same project setting every time, but in general don't do it.
Find another way such as passing a callback function pointer into the DLL that you call to add an item to the collection, and perhaps one you can call to access an item, and another you can call to clear the container, or something like that.

My homepage
Advice: Take only as directed - If symptoms persist, please see your debugger

Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

Unfortunately simplifying my production code to do exactly what is shown in my last example func1 still has issues. I stripped everything else out of it and I'm still having deallocation issues. I don't have Visual Studio 6 at home so I won't be able to create a sample project this weekend but I'll make one when I get back to work on Monday. If anyone has a suggestion of another way to do this it would be welcomed with open arms. Thanks for all of your help so far.

Sorry for not reading the entire thread since the last time I checked in, but if you're assigning new strings in the dll and the vector is destroyed in the main codeline, then that will still be the same problem (strings allocate memory).

If you really wanted to verify that this isn't the problem, and you know the maximum size of your strings, try something like this:

Long story short: the entire STL that shipped with VC++ 6 is not thread-safe, especially std:: string. Thanks for all of your help and sorry for the confusion.

It's worse than that. The STL that shipped with VC++ 6 was written before the C++ standard, so it has a rather poor implementation. There are all kinds bugs and inconsistencies with that STL implementation. There are some service packs for VC6 that fix a lot of compiler bugs which (I think) bring it pretty close to a correct implementation of the C++ standard.