|
You're welcome
Ryan "Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late" John Nichol "Point Of Impact"
|
|
|
|
|
I'm trying to write a multithreaded application in C. I'm a little new to multithreading. I would like to know whether it is required to write a seperate function for each thread. I'm using CreateThread() to create a new thread called WaveInProc. Now if I want to create one more thread do I have to create anotehr function for it. I intend to create 4 such worker threads. A similar code on MSDN had used _beginthread. But it used the same function to handle all the threads. Can someone explain how a single function can handle different threads.
|
|
|
|
|
couldn't you just have the same thread function do different things based on the arguments you pass to it?
I always use a different function for each thread I run, but that's just because I want to keep them strait when I read through the code.
|
|
|
|
|
You can reuse the same function multiple times for multiple threads. Just be careful with variables - if you access global variables, make sure you use critical sections every time you change them.
Hope this helps,
Ryan "Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late" John Nichol "Point Of Impact"
|
|
|
|
|
You should use _beginthreadex and not _beginthread neither CreateThread.
The difference is that the first one create a TIB structure type aka Thread Information Block.
This structure is important to correctly identify a thread and it's resources. After setting the TIB for the thread it ultimately calls CreateThread
Without this TIB, the c/c++ runtime engine couldn't guarante the properly cleanning of the associated thread resources.
Jeffrey Ricther in his book "Programming Windows Applications" explains it well. To check this assumptions do a search on google ... with both _beginthreadex , CreateThread and TIB ...
Joao Vaz
|
|
|
|
|
I have an edit box and use OnKillFocus to validate the user entry which can't be blank, which works fine. So if the user enters a blank entry into the edit box, a message displays telling them they can't enter blank entries.
The problem is that when the user presses the Cancel button, the edit box trys to validate the entry and displays the message box because there is not a valid entry in the edit box, and then gos around in a loop.
How can I get to keep my edit box validation but also exit if the Cancel button is clicked.
Thanks.
|
|
|
|
|
I wouldn't use OnKillFocus() , I'd do all the validation in DoDataExchange() . That way, everything is validated only when the user presses OK, or whenever you call UpdateData() . What if the user clicks in the edit box and then realises that they need to change something else in the dialog box first? They can't. Personally, I find this exceptionally annoying, and would probably stop using the program because of it. It's much more intuitive to only expect valid values when they are accepted by pressing OK.
Ryan "Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late" John Nichol "Point Of Impact"
|
|
|
|
|
Using OnKillFocus() in this fashion is a design flaw. Reconsider it. Do not enable the OK button UNTIL all controls contain valid data. For example, if you have an edit control (IDC_EDIT1) and it must be non-empty before the dialog can be dismissed, do something like:
void CMyDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_EDIT1, m_edit1);
DDX_Control(pDX, IDOK, m_okbutton);
}
BEGIN_MESSAGE_MAP(CMyDlg, CDialog)
ON_EN_CHANGE(IDC_EDIT1, OnChangeEdit1)
END_MESSAGE_MAP()
void CMyDlg::OnChangeEdit1( void )
{
m_okbutton.EnableWindow(m_edit1.GetWindowTextLength() > 0);
}
|
|
|
|
|
Has anyone ever written a book documenting all those COM/ActiveX components that ship with Visual Studio?
I've only used maybe 2 or 3 of them over the years mainly because almost none of the controls are adequately documented.
Cheers,
Tom Archer
Inside C#, Extending MFC Applications with the .NET Framework
It's better to listen to others than to speak, because I already know what I'm going to say anyway. - friend of Jörgen Sigvardsson
|
|
|
|
|
http://www.amazon.com/exec/obidos/tg/detail/-/1572315083/104-9634124-7944717?v=glance
http://images.amazon.com/images/P/1572315083.01.LZZZZZZZ.jpg
I'm ashamed to admit I own a copy of this thick book.
|
|
|
|
|
Hi,
I've SDI application with this code in CMainFrame::OnCreate() (only snippet)
__m_wndDiscBar1.CreateEx(this, TBSTYLE_WRAPABLE|TBSTYLE_FLAT | TBSTYLE_TOOLTIPS |TBSTYLE_LIST, WS_CHILD | WS_VISIBLE | CBRS_ALIGN_TOP | CBRS_TOOLTIPS|CBRS_SIZE_DYNAMIC,CRect(0,0,0,0));
__m_wndDiscBar1.type=1;
__m_wndDiscBar1.Update(false);
__m_wndDiscBar1.SetFont(getFontLW());
__m_wndDiscBar2.CreateEx(this, TBSTYLE_WRAPABLE|TBSTYLE_FLAT | TBSTYLE_TOOLTIPS |TBSTYLE_LIST, WS_CHILD | WS_VISIBLE | CBRS_ALIGN_TOP | CBRS_TOOLTIPS | CBRS_SIZE_DYNAMIC,CRect(0,0,0,0));
__m_wndDiscBar2.type=2;
__m_wndDiscBar2.Update(false);
__m_wndDiscBar2.SetFont(getFontLW());
__m_wndDoubleDiscBar.Create(this,0);
__m_wndDoubleDiscBar.ModifyStyle(0,CBRS_ALIGN_LEFT);
__m_wndDoubleDiscBar.AddBar(&m_wndDiscBar2,NULL,NULL,RBBS_NOGRIPPER|RBBS_FIXEDS
IZE);
__m_wndDoubleDiscBar.AddBar(&m_wndDiscBar1,NULL,NULL,RBBS_NOGRIPPER|RBBS_FIXEDS
IZE);
m_wndDiscBar1/2 are classes derived from CToolBar. m_wndDoubleDiscBar is CReBar instance.
Problem is in this function, which is called from CMyView::OnSize() (I have two CListViews divided by splitter)
CMainFrame::ChangeDlgBar(int cx, int dx)
{
__CReBarCtrl& RCtrl = m_wndDoubleDiscBar.GetReBarCtrl();
__REBARBANDINFO rb;
__rb.cbSize=sizeof(REBARBANDINFO);
__// THIS IS PROBLEM FUNCTION
__RCtrl.GetBandInfo(0,&rb);
__rb.cx=width;
__rb.wID=0;
__rb.fMask=RBBIM_SIZE|RBBIM_ID;
__rb.fStyle=RBBS_FIXEDSIZE|RBBS_NOGRIPPER;
__RCtrl.SetBandInfo(0,&rb);
__RCtrl.MinimizeBand(0);
.
.
}
Here is call stack:
KERNEL32! 77ec8d34()
KERNEL32! 77ec88f9()
COMCTL32! 77b9e2d5()
USER32! 77e3a244()
USER32! 77e16b21()
USER32! 77e16b44()
CWnd:efWindowProcA(CWnd * const 0x004700a0 CHinfoFileView2::OnSize(unsigned int, int, int), unsigned int 1053, unsigned int 1, long 1239272) line 1006 + 19 bytes
CWnd::WindowProc(CWnd * const 0x004700a0 CHinfoFileView2::OnSize(unsigned int, int, int), unsigned int 1053, unsigned int 1, long 1239272) line 1586 + 19 bytes
CControlBar::WindowProc(CControlBar * const 0x004700a0 CHinfoFileView2::OnSize(unsigned int, int, int), unsigned int 1053, unsigned int 1, long 1239272) line 480 + 14 bytes
CReBar::WindowProc(CReBar * const 0x004700a0 CHinfoFileView2::OnSize(unsigned int, int, int), unsigned int 1053, unsigned int 1, long 1239272) line 321 + 14 bytes
AfxCallWndProc(CWnd * 0x00000000 {CWnd hWnd=???}, HWND__ * 0x00230560, unsigned int 1053, unsigned int 1, long 1239272) line 218
AfxWndProc(HWND__ * 0x00230560, unsigned int 1053, unsigned int 1, long 1239272) line 368
USER32! 77e3a244()
USER32! 77e16362()
USER32! 77e168a4()
CReBarCtrl::GetBandInfo() line 157 + 38 bytes
CMainFrame::ChangeDlgBar(int 0, int 1) line 858
CHinfoFileView2::OnSize(unsigned int 0, int 397, int 391) line 384
CWnd::OnWndMsg(CWnd * const 0x004700a0 CHinfoFileView2::OnSize(unsigned int, int, int), unsigned int 5, unsigned int 0, long 6260016, long * 0x0012eac4) line 1964
CWnd::WindowProc(CWnd * const 0x004700a0 CHinfoFileView2::OnSize(unsigned int, int, int), unsigned int 5, unsigned int 0, long 25624973) line 1585 + 27 bytes
AfxCallWndProc(CWnd * 0x00000000 {CWnd hWnd=???}, HWND__ * 0x003d042e, unsigned int 5, unsigned int 0, long 25624973) line 218
AfxWndProc(HWND__ * 0x003d042e, unsigned int 5, unsigned int 0, long 25624973) line 368
USER32! 77e3a244()
USER32! 77e16362()
USER32! 77e14c1a()
USER32! 77e1dd30()
USER32! 77e3a244()
USER32! 77e16b21()
USER32! 77e16b44()
CWnd:efWindowProcA(CWnd * const 0x004700a0 CHinfoFileView2::OnSize(unsigned int, int, int), unsigned int 71, unsigned int 0, long 1240824) line 1006 + 19 bytes
CWnd::WindowProc(CWnd * const 0x004700a0 CHinfoFileView2::OnSize(unsigned int, int, int), unsigned int 71, unsigned int 0, long 1240824) line 1586 + 19 bytes
AfxCallWndProc(CWnd * 0x00000000 {CWnd hWnd=???}, HWND__ * 0x003d042e, unsigned int 71, unsigned int 0, long 1240824) line 218
AfxWndProc(HWND__ * 0x003d042e, unsigned int 71, unsigned int 0, long 1240824) line 368
USER32! 77e3a244()
USER32! 77e14730()
USER32! 77e174b4()
NTDLL! 77f91a7f()
COMCTL32! 77b59ddf()
COMCTL32! 77b55af5()
COMCTL32! 77b5b24d()
USER32! 77e3a244()
USER32! 77e16b21()
USER32! 77e16b44()
CWnd:efWindowProcA(CWnd * const 0x004700a0 CHinfoFileView2::OnSize(unsigned int, int, int), unsigned int 11, unsigned int 1, long 0) line 1006 + 19 bytes
CWnd::WindowProc(CWnd * const 0x004700a0 CHinfoFileView2::OnSize(unsigned int, int, int), unsigned int 11, unsigned int 1, long 0) line 1586 + 19 bytes
AfxCallWndProc(CWnd * 0x00000000 {CWnd hWnd=???}, HWND__ * 0x003d042e, unsigned int 11, unsigned int 1, long 0) line 218
AfxWndProc(HWND__ * 0x003d042e, unsigned int 11, unsigned int 1, long 0) line 368
USER32! 77e3a244()
USER32! 77e16362()
USER32! 77e168a4()
CWnd::SetRedraw() line 120 + 33 bytes
CHinfoFTPDoc::listFiles(CListCtrl * 0x11136980 {CHinfoFileView2 hWnd=0x003d042e}, const char * 0x00000000, int 0, CMyFileView * 0x11136980 {CHinfoFileView2 hWnd=0x003d042e}, int 0) line 993
CHinfoFileView2::OnInitialUpdate() line 259
CWnd::OnWndMsg(CWnd * const 0x004700a0 CHinfoFileView2::OnSize(unsigned int, int, int), unsigned int 868, unsigned int 0, long 6320368, long * 0x0012fbc8) line 1825
CWnd::WindowProc(CWnd * const 0x004700a0 CHinfoFileView2::OnSize(unsigned int, int, int), unsigned int 868, unsigned int 0, long 0) line 1585 + 27 bytes
AfxCallWndProc(CWnd * 0x00000000 {CWnd hWnd=???}, HWND__ * 0x003d042e, unsigned int 868, unsigned int 0, long 0) line 218
CWnd::SendMessageToDescendants(HWND__ * 0x004d052e, unsigned int 868, unsigned int 0, long 0, int 1, int 1) line 2309
CWnd::SendMessageToDescendants(HWND__ * 0x0027045e, unsigned int 868, unsigned int 0, long 0, int 1, int 1) line 2318 + 21 bytes
CFrameWnd::InitialUpdateFrame(CFrameWnd * const 0x004700a0 CHinfoFileView2::OnSize(unsigned int, int, int), CDocument * 0x1113fdc8 {CHinfoFTPDoc}, int 1) line 753
CDocTemplate::InitialUpdateFrame(CDocTemplate * const 0x004700a0 CHinfoFileView2::OnSize(unsigned int, int, int), CFrameWnd * 0x11181188 {CMainFrame hWnd=0x0027045e}, CDocument * 0x1113fdc8 {CHinfoFTPDoc}, int 1) line 332
CSingleDocTemplate::OpenDocumentFile(CSingleDocTem
plate * const 0x004700a0 CHinfoFileView2::OnSize(unsigned int, int, int), const char * 0x00000000, int 1) line 205
CDocManager::OnFileNew(CDocManager * const 0x004700a0 CHinfoFileView2::OnSize(unsigned int, int, int)) line 829
_AfxDispatchCmdMsg(CCmdTarget * 0x00640cf8 class CHinfoFTPApp theApp, unsigned int 57600, int 0, void (void)* 0x005b7670 CWinApp::OnFileNew(void), void * 0x00000000, unsigned int 12, AFX_CMDHANDLERINFO * 0x00000000) line 88
CCmdTarget::OnCmdMsg(CCmdTarget * const 0x004700a0 CHinfoFileView2::OnSize(unsigned int, int, int), unsigned int 57600, int 0, void * 0x00000000, AFX_CMDHANDLERINFO * 0x00000000) line 302 + 24 bytes
CWinApp::ProcessShellCommand(CWinApp * const 0x004700a0 CHinfoFileView2::OnSize(unsigned int, int, int), CCommandLineInfo & {CCommandLineInfo}) line 31 + 23 bytes
CHinfoFTPApp::InitInstance() line 377 + 12 bytes
AfxWinMain(HINSTANCE__ * 0x00400000, HINSTANCE__ * 0x00000000, char * 0x00133feb, int 1) line 39 + 7 bytes
WinMain(HINSTANCE__ * 0x00400000, HINSTANCE__ * 0x00000000, char * 0x00133feb, int 1) line 30
HINFOFTP! WinMainCRTStartup + 224 bytes
KERNEL32! 77ea847c()
[/php]
I went deeper for the cause of the access violation and found possible problem in this code:
LRESULT CALLBACK AfxWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
__// special message which identifies the window as using AfxWndProc
__if (nMsg == WM_QUERYAFXWNDPROC)
____return 1;
__// all other messages route through message map
__CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);
__ASSERT(pWnd != NULL);
__ASSERT(pWnd->m_hWnd == hWnd);
__return AfxCallWndProc(pWnd, hWnd, nMsg, wParam, lParam);
}
because CWnd::FromHandlePermanent(hWnd) returns NULL. But hWnd is valid (or at least the same value as I could see imediately after CReBar::Create() being finished)
But what's most confusing for me - this access violation only appears when I build release build with debug info (For Edit And Continue). When I build release build without debug info or when I build debug info, no access violation happens.
I'm really out....
Could someone help me?
I will appreciate any suggestion.
|
|
|
|
|
s_k wrote:
__REBARBANDINFO rb;
__rb.cbSize=sizeof(REBARBANDINFO);
__// THIS IS PROBLEM FUNCTION
__RCtrl.GetBandInfo(0,&rb);
try
_REBARBANDINFO rb;
::ZeroMemory(&rb, sizeof(REBARBANDINFO));
__rb.cbSize=sizeof(REBARBANDINFO);
|
|
|
|
|
IT WORKS!!
I thank you so much!
Anyway, if you answered me this question, I would be even more happy: How is it possible that neither in debug version nor in release version without debug info no access violation appeared? Maybe I would understand difference between debug and clean release version, but what the heck is difference between, we can say, two DEBUG versions?
Thank you again, AlexO, I really appreciate your help!
|
|
|
|
|
It is very common error in debug vs. release. The problem is debug memory allocation it usually initializes memory to 0 or 0xcdcdcdcd.
Release memory is not initialized so values are random. Example:
DWORD dwSize; //not that is not initialized
SomeFunction(&dwSize);//note dwSize is in/out parameter
the example above might work in debug but will blow up in release.
|
|
|
|
|
I don't understand.
dwSize is just local variable. Its address (as passed to SomeFunction()) will be always valid, won't be? Of course SomeFunction() mustn't do something like this:
TCHAR* s = new TCHAR[dwSize];
because dwSize was not initialized, but the code you posted itself is valid as long as I don't know SomeFunction() code...
|
|
|
|
|
no, I did not mean address. Imagine that inside that function you have soemthing like
int SomeFunction(DWORD* dwSize, char* actualBuffer)
{
if(*dwSize > 0)
{
char* pCopy = new char[*dwSize];
::memcpy(pCopy, actualBuffer, *dwSize);//this is where error will manifest itself if you forgot to initialize dwSize, in release dwSize could be anything, in debug it would probably be zero so we never come here
...
}
...
}
P.S. Real scenario is usually more complex but idea is the same
|
|
|
|
|
Yes, I understand now, that's what I thought could really cause problems...
|
|
|
|
|
A few things I'd try:
1) Always test functions succeed. In particular CreateEx(), Create() etc.
2) In CMainFrame::ChangeDlgBar() add:
ASSERT_VALID( this );
ASSERT( ::IsWindow( m_hWnd );
ASSERT( ::IsWindow( m_wndDoubleDiscBar.m_hWnd ) );
__CReBarCtrl& RCtrl = m_wndDoubleDiscBar.GetReBarCtrl();
ASSERT_VALID( &RCtrl );
ASSERT( ::IsWindow( RCtrl.m_hWnd );
Neville Franks, Author of ED for Windows. Free Trial at www.getsoft.com
|
|
|
|
|
Thanks Neville! Fortunately, AlexO has already found the cause of the problem - I have to call ::ZeroMemory to zero REBARBANDINFO structure. Never thought this may be reason for CWnd::FromHandlePermanent() to return NULL...
|
|
|
|
|
Yes I saw Alex's post just after I sent mine. Initialization issues like this can be hard to track down and the outcome can vary depend on what crap happens to be being set. Bottom line is your back in business.
Neville Franks, Author of ED for Windows. Free Trial at www.getsoft.com
|
|
|
|
|
In debug mode build, the linker assigns bogus size storage for each block. When you accidentally forgotten to delete or deinitialize some component. The extra size storage in each other block can still cater as it had not touched the actual content. But once the linker had swicthed to release mode. All the storage blocks were optimise to it supposing size. When you have crossing action in your code, straight up a access violation will pop up.
I read this in one of codeproject article. Can't remember the title already but hope this helps.
|
|
|
|
|
I know I probably forgot to call a default class member when building some message handler or another but this is really aggravating.
I have a dialog based app and the app exits if you hit the enter key.
I really wish it didn't do this.
Could anyone help?
|
|
|
|
|
The enter key activates the default button of the dialog which is usually the Ok button..
John
|
|
|
|
|
John M. Drescher wrote:
The enter key activates the default button of the dialog which is usually the Ok button..
Thanks - I'm an idiot. That's the first thing I thought of, and I know it is true from so many other apps and is just a Windows basic user-level thing but I totally forgot about that and was mixing it up with the space bar ala the currently active control.
I guess I will change the control ID for the button. :sheepish grin:
|
|
|
|
|
tnolley wrote:
I guess I will change the control ID for the button.
Changing the control ID won't solve your problem. The most simple way is to override CDialog::OnOK(). You might want to override CDialog::OnCancel() as well, in case you don't want the dialog to get closed when you hit the escape key.
CMyDialog::OnOK(){ return; }
// Afterall, I realized that even my comment lines have bugs
When one cannot invent, one must at least improve (in bed).-My latest fortune cookie
|
|
|
|
|