vector<wxString> problem ?

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
Lloyd
Super wx Problem Solver
Super wx Problem Solver
Posts: 350
Joined: Wed May 03, 2006 2:36 pm
Location: India
Contact:

vector<wxString> problem ?

Post by Lloyd » Wed Jun 04, 2008 6:20 am

Hi,
I am using a vector<wxString> in my program and it causes a debug assertion in Windows2000. My application name is pacektanalyzer.exe

The error message is as follows...

Windows has triggered a breakpoint in Packetanalyzer.exe
This may due to corruption in the heap, and includes a bug in PacketAnalyzer.exe or any of the DLLs it has loaded.



The call stack is given below

Code: Select all

	msvcr80d.dll!_free_dbg_nolock(void * pUserData=0x02552c60, int nBlockUse=1)  Line 1252 + 0x30 bytes	C++

 	msvcr80d.dll!_free_dbg(void * pUserData=0x02552c60, int nBlockUse=1)  Line 1194 + 0xd bytes	C++

 	msvcr80d.dll!free(void * pUserData=0x02552c60)  Line 1152 + 0xb bytes	C++

 	wxbase28ud_vc_custom.dll!wxStringData::Unlock()  Line 243 + 0x3f bytes	C++

 	wxbase28ud_vc_custom.dll!wxStringBase::~wxStringBase()  Line 397	C++

 	wxbase28ud_vc_custom.dll!wxString::~wxString()  + 0x16 bytes	C++

 	PacketAnalyzer.exe!wxString::`scalar deleting destructor'()  + 0x2e bytes	C++

 	PacketAnalyzer.exe!std::_Destroy<wxString>(wxString * _Ptr=0x0275a238)  Line 61	C++

 	PacketAnalyzer.exe!std::allocator<wxString>::destroy(wxString * _Ptr=0x0275a238)  Line 161 + 0x9 bytes	C++

 	PacketAnalyzer.exe!std::_Destroy_range<wxString,std::allocator<wxString> >(wxString * _First=0x0275a238, wxString * _Last=0x0275a23c, std::allocator<wxString> & _Al={...}, std::_Nonscalar_ptr_iterator_tag __formal={...})  Line 235 + 0xc bytes	C++

 	PacketAnalyzer.exe!std::_Destroy_range<wxString,std::allocator<wxString> >(wxString * _First=0x0275a238, wxString * _Last=0x0275a23c, std::allocator<wxString> & _Al={...})  Line 226 + 0x2e bytes	C++

 	PacketAnalyzer.exe!std::vector<wxString,std::allocator<wxString> >::_Destroy(wxString * _First=0x0275a238, wxString * _Last=0x0275a23c)  Line 1083 + 0x14 bytes	C++

 	PacketAnalyzer.exe!std::vector<wxString,std::allocator<wxString> >::_Tidy()  Line 1096	C++

 	PacketAnalyzer.exe!std::vector<wxString,std::allocator<wxString> >::~vector<wxString,std::allocator<wxString> >()  Line 547	C++

 	PacketAnalyzer.exe!ProcessFilter::ExecuteUserFilter(wxString FilterExp={...})  Line 597 + 0x59 bytes	C++


My code snippet is also given

Code: Select all


wxString Filter::ExecuteUserFilter(wxString FilterExp)
{
......
....
  vector<wxString> FilesNames;
  wxStructStat FileStatus;
  wxFileOffset TotalFileLength=0,OverAllBytesRead=0;
  wxString fn;
  while(QueryResult.NextRow()) //This a sqlite3 database select result set access fn.
  {
   fn=QueryResult.GetString(0);	   
   FilesNames.push_back(fn);
   ...
  }
.....
......
}


Can you give me some hints?

achim
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 205
Joined: Sun Aug 29, 2004 5:20 pm
Location: Germany

Post by achim » Wed Jun 04, 2008 8:23 am

hi,

let's see the implementation of std::_Destroy<wxString>(wxString*), line 61 (don't know witch file)

JimFairway
wxWorld Domination!
wxWorld Domination!
Posts: 1059
Joined: Sun Dec 30, 2007 6:40 pm
Location: Canada

Post by JimFairway » Wed Jun 04, 2008 11:49 am

Hi,

Based on the trace, it looks like vector is deleting all the objects in FilesNames when Filter::ExecuteUserFilter exits. This is because FilesNames is local on the stack.
Because you have added the same object 'fn' to your vector multiple times, it crashes when it tries to delete the second entry in the vector (which is fn again with different contents).

Try

Code: Select all

  wxString *fn;
  while(QueryResult.NextRow()) //This a sqlite3 database select result set access fn.
  {
   fn=new wxString(QueryResult.GetString(0));    
   FilesNames.push_back(*fn);
   ...
  }
When the routine exits, I believe vector will clean up all the strings on the heap.

Hope that helps,

Jim
OS: Vista SP1, wxWidgets 2.8.7.

Belgabor
I live to help wx-kind
I live to help wx-kind
Posts: 173
Joined: Mon Sep 25, 2006 1:12 pm

Post by Belgabor » Wed Jun 04, 2008 12:11 pm

No, push_back copies the argument, so his code is ok. Personally I would think it's a bug in MS's std lib and try STLport.

phlox81
wxWorld Domination!
wxWorld Domination!
Posts: 1387
Joined: Thu Aug 18, 2005 7:49 pm
Location: Germany
Contact:

Post by phlox81 » Wed Jun 04, 2008 12:19 pm

JimFairway wrote:

Code: Select all

  wxString *fn;
  while(QueryResult.NextRow()) //This a sqlite3 database select result set access fn.
  {
   fn=new wxString(QueryResult.GetString(0));    
   FilesNames.push_back(*fn);
   ...
  }
When the routine exits, I believe vector will clean up all the strings on the heap.
No, thats a memoryleak. std::vector<wxString> should work.
So maybe its a linker problem, are the runtimes both the same?
Or its a MSVC Bug, but I don't think, that this is a bug. std::vector is used to often for this.

Jorg
Moderator
Moderator
Posts: 3971
Joined: Fri Aug 27, 2004 9:38 pm
Location: Delft, Netherlands
Contact:

Post by Jorg » Wed Jun 04, 2008 1:01 pm

Lloyd,

Maybe the copy constructor v.s assignment operator is not working properly. What if you recreate the string object everytime the object needs to be copied?

Code: Select all

wxString Filter::ExecuteUserFilter(wxString FilterExp)
{
......
....
  vector<wxString> FilesNames;
  wxStructStat FileStatus;
  wxFileOffset TotalFileLength=0,OverAllBytesRead=0;
  wxString fn;
  while(QueryResult.NextRow()) //This a sqlite3 database select result set access fn.
  {
   fn=QueryResult.GetString(0);     <---- assignment operator  here
   FilesNames.push_back(fn);        <----- copy construction here
   ...
  } 
Change this to;

Code: Select all

wxString Filter::ExecuteUserFilter(wxString FilterExp)
{
......
....
  vector<wxString> FilesNames;
  wxStructStat FileStatus;
  wxFileOffset TotalFileLength=0,OverAllBytesRead=0;
  while(QueryResult.NextRow()) //This a sqlite3 database select result set access fn.
  {
     wxString tmp(QueryResult.GetString(0));     <---- force a copy constructor
   FilesNames.push_back(tmp);       
   ...
  } 
This ensures you of a new object you copy from every time. Maybe something is fishy with refcounting and such that the assignment operator copies a refcount along and doesn't want to properly free it.

- Jorgen
Forensic Software Engineer
Netherlands Forensic Insitute
http://english.forensischinstituut.nl/
-------------------------------------
Jorg's WasteBucket
http://www.xs4all.nl/~jorgb/wb

Auria
Site Admin
Site Admin
Posts: 6695
Joined: Thu Sep 28, 2006 12:23 am
Contact:

Post by Auria » Wed Jun 04, 2008 2:55 pm

Take a look at wxArrayString, it was dsigned with wxStrings in mind

Lloyd
Super wx Problem Solver
Super wx Problem Solver
Posts: 350
Joined: Wed May 03, 2006 2:36 pm
Location: India
Contact:

Post by Lloyd » Wed Jun 04, 2008 3:09 pm

One more thing I would like to mention is, in release build it works, no problem. But this problem occurs in debug build!! In linux also this works fine.

I tried Jorgen's suggestion, but the same problem repeated :(

Thanks,
Lloyd

Frank
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 211
Joined: Sat Jan 01, 2005 6:19 pm

Post by Frank » Wed Jun 04, 2008 3:37 pm

I think you problem is not the vector. vector is fine and tested by millions of uses in thousands of programs.

Thing is, in debug mode the CRT performs a check of the memory structures on every new/delete. So the destructor of the vector is not the place where the corruption is caused. It's just the place where the CRT finds it, when it performes it's heap-check.

I would look before that code. I think you are overwriting some piece of memory, wich causes the control-bytes, wich are in front and behind of every memory block in debug mode, to be overwritten, wich ccauses the CRT to complain about coruption.

Post Reply