// JP opened flex table

Click to See Complete Forum and Search --> : CString crashes my application


Amit Sebiz
April 5th, 2004, 06:25 AM
Hi

I am making an multithreaded application. In which i use strings stored in a listbox sequentially. Thing is that it works fine for about 400 strings but after that gives an assertion failure and later access voilation error.

I have traced the code the comes due to assertion failure in ReleaseBuffer function of CString.

Can anyone tell me why. And how to tackle this problem.

Amit

Marc from D
April 5th, 2004, 06:37 AM
When I had similar problems it always turned out that I had something like this:

CString t[100]
for (i = 0; i<=100; i++)
t[i] =....
This uses 0..100, but 100 is not valid!

Marc

VictorN
April 5th, 2004, 06:44 AM
HI, Amit Sebiz!
Could you post the code giving "an assertion failure and later access voilation error"?

Alin
April 5th, 2004, 06:48 AM
Originally posted by Amit Sebiz
Hi

I am making an multithreaded application. In which i use strings stored in a listbox sequentially. Thing is that it works fine for about 400 strings but after that gives an assertion failure and later access voilation error.

I have traced the code the comes due to assertion failure in ReleaseBuffer function of CString.

Can anyone tell me why. And how to tackle this problem.

Amit

do you write the strings into the listbox from the thread or in the thread you read these strings from the listbox and do something with them?
in any case post the relevant code.

Amit Sebiz
April 5th, 2004, 06:50 AM
A good suggestion , But has not served my purpose.

By the way thnx

Amit Sebiz
April 5th, 2004, 06:54 AM
hi, this is the code that is creating problem, this function is being called by all the threads.

m_criticalSectionFire.Lock();

for(int nCount=1;nCount<30;nCount++)//to be changed to 30
{
if((!g_threadinfo[nCount].bState)&&m_URLs.GetCount()>nURLs)//nCount.e. if number of URls is < max
{
g_threadinfo[nCount].sUrl="";
g_threadinfo[nCount].sUrl.FreeExtra();
m_URLs.GetText(nURLs++,g_threadinfo[nCount].sUrl);
g_threadinfo[nCount].pView=this;
g_threadinfo[nCount].nMe=nCount;
g_threadinfo[nCount].bState=true;
pSearchThread[nCount]=AfxBeginThread(g_fnSearchURL,(LPVOID)&g_threadinfo[nCount]);
}
}
m_criticalSectionFire.Unlock();

Amit Sebiz
April 5th, 2004, 06:59 AM
g_threadinfo-> an array of thread information structure as given below

struct threadinfo
{
short nMe;
CString sUrl;
CSpiderView *pView;
BOOL bState;
} ;

threadinfo g_threadinfo[30] ;

bState tell me if thread is running or not. nMe is custom id given to the thread.

nURLs -> current URL in the list

VictorN
April 5th, 2004, 07:27 AM
And Where is ReleaseBuffer" causing the assertion?

Amit Sebiz
April 5th, 2004, 07:31 AM
Release buffer is called by GetText member function of CListBox,
following r the last parts of the dump given by VC++ 6.0 debugger, may be of some help.


memory check error at 0x00C93AC7 = 0x71, should be 0xFD.
memory check error at 0x00C93AC8 = 0x31, should be 0xFD.
memory check error at 0x00C93AC9 = 0x00, should be 0xFD.
The thread 0x624 has exited with code 3 (0x3).
The thread 0x954 has exited with code 3 (0x3).
The thread 0x7E8 has exited with code 3 (0x3).
The thread 0x6CC has exited with code 3 (0x3).
The thread 0x7B4 has exited with code 3 (0x3).
The thread 0x824 has exited with code 3 (0x3).
The thread 0x594 has exited with code 3 (0x3).
The thread 0x2EC has exited with code 3 (0x3).
The thread 0x7A0 has exited with code 3 (0x3).
The thread 0x87C has exited with code 3 (0x3).
The thread 0x800 has exited with code 3 (0x3).
The thread 0x8E4 has exited with code 3 (0x3).
The thread 0x89C has exited with code 3 (0x3).
The thread 0x5C8 has exited with code 3 (0x3).
The thread 0x79C has exited with code 3 (0x3).
The thread 0x708 has exited with code 3 (0x3).
The thread 0x580 has exited with code 3 (0x3).
The thread 0x804 has exited with code 3 (0x3).
The thread 0x7C8 has exited with code 3 (0x3).
The thread 0x67C has exited with code 3 (0x3).
The thread 0x91C has exited with code 3 (0x3).
The thread 0x4F8 has exited with code 3 (0x3).
The thread 0x86C has exited with code 3 (0x3).
The thread 0x294 has exited with code 3 (0x3).
The thread 0x5B0 has exited with code 3 (0x3).
The thread 0x814 has exited with code 3 (0x3).
The thread 0x8BC has exited with code 3 (0x3).
The thread 0x8AC has exited with code 3 (0x3).
The thread 0x60C has exited with code 3 (0x3).
The thread 0x8DC has exited with code 3 (0x3).
The thread 0x838 has exited with code 3 (0x3).
The thread 0x844 has exited with code 3 (0x3).
The thread 0x26C has exited with code 3 (0x3).
The thread 0x914 has exited with code 3 (0x3).
The thread 0x928 has exited with code 3 (0x3).
The thread 0x2AC has exited with code 3 (0x3).
The thread 0x8EC has exited with code 3 (0x3).
First-chance exception in Spider.exe (MFC42D.DLL): 0xC0000005: Access Violation.
First-chance exception in Spider.exe (MFC42D.DLL): 0xC0000005: Access Violation.

Andreas Masur
April 5th, 2004, 07:55 AM
[Moved thread]

Mick
April 5th, 2004, 07:58 AM
memory check error at 0x00C93AC7 = 0x71, should be 0xFD.
memory check error at 0x00C93AC8 = 0x31, should be 0xFD.
memory check error at 0x00C93AC9 = 0x00, should be 0xFD.


Your overwriting memory the debug CRT pads default 4 bytes before and 4 bytes after memory with 0xFD, the lines above indicate you've overwritten those bytes, breakpoint or examine those memory locations in the debugger to find out where you are doing this, fix that, and your problems should go away (if you don't have more underlying issues that is)

Amit Sebiz
April 5th, 2004, 08:14 AM
Mick,

But exactly how i will do that.

Mick
April 5th, 2004, 08:29 AM
Originally posted by Amit Sebiz
Mick,

But exactly how i will do that.

well what is your experience level using a debugger, I'll assume your going to use the IDE debugger for now. At anyrate let me explain a bit more and give an example, and someday, somebody will write a FAQ on this for CG, I'll contribute, but I ain't got no time for that.

at anyrate. Generally people overwrite memory when manipulating arrays. The below tells you, that at addresses:

0x00C93AC7, you have three bytes extending into the pad, 0x71, 0x31, 0x00 (which looks like a null terminated string, that just extended a wee bit too far)

memory check error at 0x00C93AC7 = 0x71, should be 0xFD.
memory check error at 0x00C93AC8 = 0x31, should be 0xFD.
memory check error at 0x00C93AC9 = 0x00, should be 0xFD.

So in the debugger, you would breakpoint when you start your application. Select debug->breakpoints, and set a data watch on 0x00C93AC7, this will break when that memory location changes, then you examine the code, if your not writing to it, then keep going, if you are writing to it, then open the memory window from the debug windows, and put that address in the memory window, you'll see the first 4 bytes are padded by 0xFD, and the last bytes are padded by 0xFD say your size of memory is twenty, you'll have a pad, then twenty bytes, then the end pad. Just watch for when those values of FD change to 0x71 etc, that is where you are overwriting memory, fix the code at that point.

so lets break this down into an example.


int main(int argc, char* argv[])
{
char* foo = new char[4];
memset(foo,7,6);
delete [] foo;
return 0;
}


memory when foo is allocated *foo in the memory window:


00322568 2E 00 00 00 FD FD FD FD ....ýýýý
00322570 CD CD CD CD FD FD FD FD ÍÍÍÍýýýý
00322578 0D F0 AD BA 0D F0 AD BA .ð_º.ð_º


CD is the default fill for 'new'd memory so 4 bytes CD and you can see the pads of FD. now the memset which will overwrite the allocated memory.


00322568 2E 00 00 00 FD FD FD FD ....ýýýý
00322570 07 07 07 07 07 07 FD FD ......ýý
00322578 0D F0 AD BA 0D F0 AD BA .ð_º.ð_º


now when I call delete [] the debug crt will raise a breakpoint becuase it sees that I have overwritten memory and the output window in the debugger will display:

memory check error at 0x00322574 = 0x07, should be 0xFD.
memory check error at 0x00322575 = 0x07, should be 0xFD.


if I hit retry and jump into the debugger, and walk up the stack trace I will come to where I call delete [] so I know that I've overwritten foo. Now I can restart my program and set a data breakpoint for 0x00332574 and watch it in the memory window and wait for it to break (if the sample I posted were more complex this is where it would help you out) then I would find, the point where I do memset and say ohh I'm overwriting by 2 bytes, need to fix that, and I'm done.

Hope that helps out. Once you get familiar with that, then you can jump to using the _CrtXXX functions to further help your application identify problems <crtdbg.h>

There is plenty of documentation/articles on how to use the IDE debugger on msdn.microsoft.com

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vsdebug/html/_asug_how_do_i_topics3a_debugging.asp

Amit Sebiz
April 5th, 2004, 09:15 AM
there is a problem, the address of error is changing every time. Actually, i know that CString object is being creating problems it seems that new datalength for CString object is more than the allocated length but this is done internally by CString itself, Is there a problem with CString or is that CListBox return the pointer to its buffer instead of copying the data to buffer.

Is it possible that i at anytime i my CString object be given enough memory(it may be redundant) at the start, as i there is a limit on the size of URLs.

One more question, may be a possibility, do CString objects have any size limits.

cvogt61457
April 5th, 2004, 09:25 AM
What is m_URLs?

Is this your List box?

Are you attempting to access a list box GUI object from a worker
thread?

If so, then this could be the cause of your problem.

Do not access any GUI object (MFC or API) from a worker thread.
Only use the main GUI thread to do this.

This is are problem because the GUI objects are not thread-safe.
You cannot expect that you can access the same GUI object from
different threads.

VictorN
April 5th, 2004, 09:29 AM
One more question, may be a possibility, do CString objects have any size limits.Yes, about 2^31 ;)
However, IMHO, it is not a problem in your case.
Why not to set a breakpoint (F9) at the line:m_URLs.GetText(nURLs++,g_threadinfo[nCount].sUrl);
and to debug, and to see all your local values, including nCount, nURLs++, ... and so on?

Amit Sebiz
April 5th, 2004, 10:00 AM
First of all, i have tried using breakpoint at

m_URLs.GetText(nURLs++,g_threadinfo[nCount].sUrl);

As this only told me that the problem is arising due to data transfer between listbox and cstring.

Second, i have to use worker threads to access UI elements as the application speed is so fast that if mainthread updates UI elements, application will go not responding for the whole period (not good).

and also this system worked fine with earlier applications but the problem has appeared here only.

Also, i am using critical sections to limit the code access(which acceses UI elemnts) to one thread at a time. So, no problem of multiple threads accessing the code at one time.

Mick
April 5th, 2004, 11:48 AM
Use <crtdbg.h> and insert a _CrtCheckMemory() right after you transfer the data from the listbox to the CString, use a breakpoint for each and every iteration you do, when the debug output window shows the memory corruption, then look in the debugger at the values, string lengths etc. This is not really hard to do, it should be very evident to you via the debugger what the problem is.

Sam Hobbs
April 5th, 2004, 01:04 PM
A CString size is essentially unlimited but listbox is not. You should check the return value from AddString and InsertString to ensure you are not exceeding the space for the listbox.

Amit Sebiz
April 6th, 2004, 12:08 AM
Originally posted by Sam Hobbs
A CString size is essentially unlimited but listbox is not. You should check the return value from AddString and InsertString to ensure you are not exceeding the space for the listbox.

What's the maximum size of a ListBox string, Ichecked in MSDN but found nothing.

Sam Hobbs
April 6th, 2004, 12:35 AM
I know there is a limit but as best as I remember there is not a specific maximum. The limit is dependent on the data. I tried to find where that is described before making my first reply. So that is why you should check the return code, since that is good advice regardlous.

Amit Sebiz
April 6th, 2004, 02:54 AM
Hi everybody,

I think problem is solved (because the application has completed without crashing) but i will check it out with some more inputs, hope it will not come back again.

It was actually due to crossing of some limit in Listbox (i didn't find out what's the limit) but i actually put up a realistic one(keeping the performance of application into account offcourse) on number of elemnts in listbox.

By the Thanks evevryone for your help and suggestions.

Ciao,
Amit

VictorN
April 6th, 2004, 03:34 AM
About the limits for CListBox...
According to MSDN ("CListBox::InitStorage"): ....
Windows 95 only: The nItems parameter is limited to 16-bit values. This means list boxes cannot contain more than 32,767 items. Although the number of items is restricted, the total size of the items in a list box is limited only by available memory.

cvogt61457
April 12th, 2004, 09:48 AM
Read this on accessing MFC objects from other threads.

MS Topics on Multi-threading (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore98/html/_core_multithreading_with_c.2b2b_.and_mfc.asp)


From MSDN online:
Windows Handle Maps
As a general rule, a thread can access only MFC objects that it created. This is because temporary and permanent Windows handle maps are kept in thread local storage to ensure protection from simultaneous access from multiple threads. For example, a worker thread cannot perform a calculation and then call a document’s UpdateAllViews member function to have the windows that contain views on the new data modified. This will have no effect at all, because the map from CWnd objects to HWNDs is local to the primary thread. This means that one thread may have a mapping from a Windows handle to a C++ object, but another thread may map that same handle to a different C++ object. Changes made in one thread would not be reflected in the other.



How do you create your threads?
Are your threads UI Threads, Worker threads, or created with
Win32 API directly?

//JP added flex table