|
I have a C++ dll (native using MFC), it is used from a few different applications. It works much of the time and has no memory issues that Purify can see. But the dll sometimes exits for no reason. No error is reported, it is not a crash or lockup. Since the Dll exits, it causes the application that uses it to exit too. Having no error reported, closing the forms, and being intermitant makes this difficult to debug. Any advise about what to look for in the code that typically causes this type of behaviour (other than forgetting to return)? Yes, the debugger could help but I have not been able to reproduce on a development PC yet.
TBC
|
|
|
|
|
Sorry if this is pretty unhelpful but you could (and this would be PRETTY laborious) open a file stream and write data to it when certain tasks are performed in the DLL and also (if you can) write a message to the file when the DLL exits to determine what has happened..
I'm pretty sure it's not a memory buffer overload.. This would result in the application crashing, not just exiting.. However I'm not certain so a memory issue could be the problem.
Sorry I can't be of more help, but I don't have any of the source code to see for myself..
Hope this helps!
--PerspX
"Nowadays, security guys break the Mac every single day. Every single day, they come out with a total exploit, your machine can be taken over totally. I dare anybody to do that once a month on the Windows machine." - Bill Gates
|
|
|
|
|
Thanks PerspX for the quick reply. That's what I needed to hear. I thought maybe I was missing another obvious cause of this symptom. File logging was a last resort. It's a fairly complicated dll with only a few public functions. Sorry I can't post any code, but I'm not permitted.
TBC
|
|
|
|
|
Yeah that's fine it also may help you to sort out any other bugs and even possibly make your coding more efficient
--PerspX
"Nowadays, security guys break the Mac every single day. Every single day, they come out with a total exploit, your machine can be taken over totally. I dare anybody to do that once a month on the Windows machine." - Bill Gates
|
|
|
|
|
Are you using Threads in your DLL?
Unexplainable phenomenon - The try-catch in main function did not catch exceptions in a dll's thread. The exact same *complete- and silent exit* happened to my app.
It turned out that if a thread in the dll has an AccessViolation, accessing a NULL-element on a primitive-type array or other dangling reference problem, the exception catch of the host-app do not catch the execption in the dll's thread.
I think you should evaluate all array accessing routines and life-span of objects and its pointer contexts. -Or implement a errorlog. But I think by the time you find the faulty pointer or array, you well could've implemented a errorlog.
You should take this problem as a wake-up call for *your code is too complicated*. Debugging Spaghetti is not fun and a errorlog would help.
Hope this helps.
|
|
|
|
|
1) What is the difference between handle and pointer in terms of memory. Can my other process(non releated) see a handle/pointer. Lets say if my application has a pointer pointing to some data at at that memory location. Will it be possible for the other application to access that data? How?
2) What will one try to use LoadLibrary which shall load a exe and not execute it?
3) The return value from WinExec, which is a stripped-down version of CreateProcess, is a handle to a Windows NT executive object, whereas an instance handle, the value returned from LoadLibrary, is a virtual pointer.
|
|
|
|
|
tom groezer wrote: What is the difference between handle and pointer in terms of memory.
A handle is an "opaque" data type. You can't make any assumptions about what it is and the
implementation can be changed (in future versions) at any time. A handle could be a pointer, an
index, an atom, etc. A handle is NOT always a pointer.
tom groezer wrote: Can my other process(non releated) see a handle/pointer. Lets say if my application has a pointer
pointing to some data at at that memory location. Will it be possible for the other application
to access that data?
Each process has its own address space. You could pass a pointer to another process but the
pointer would be useless to the other process. To share memory between processes you could use
something like GlobalAlloc, which allocates memory on the global heap.
tom groezer wrote: The return value from WinExec, which is a stripped-down version of CreateProcess, is a handle to a
Windows NT executive object, whereas an instance handle, the value returned from LoadLibrary, is
a virtual pointer.
You seem to know alot about internal details like that Who cares, both functions are holdovers
from 16-bit Windows.
Mark
Mark Salsbery
Microsoft MVP - Visual C++
This episode brought to you by the letter Z
|
|
|
|
|
Is GlobalAlloc still valid in 32 bit systems. Also what is the transition of heap from 16 bit to 32 bits systems done to get rid of a global heap. Another offshoot of this question is where do the global objects and staic objects kept. Is it kept in a special area in memory.
The question was what is meant by a virtual pointer.
|
|
|
|
|
tom groezer wrote: The question was what is meant by a virtual pointer.
tom groezer wrote: whereas an instance handle, the value returned from LoadLibrary, is a virtual pointer
I thought LoadLibrary returned a handle. That's why I stated you seem to know the internals
Maybe the first few sentences at this link explain it?
Virtual Address Space[^]
And more on global/local 16/32-bit... Global and Local Functions[^]
tom groezer wrote: where do the global objects and staic objects kept.
In the object files? The EXE file? in memory when the process is created and the exe is loaded?
More great reading Peering Inside the PE: A Tour of the Win32 Portable Executable File Format[^]
Mark Salsbery
Microsoft MVP - Visual C++
This episode brought to you by the number 3
|
|
|
|
|
Volatile type qualifier. The keyword declares a variable that's accessible by other processes. I don't know much about the subject and not many books talk about it. I think theres reason for it being a discreet matter .
Check out http://msdn2.microsoft.com/en-us/library/888bfst6(VS.80).aspx it gives an overview - you need to dig more for implantation examples.
Hope it helps.
|
|
|
|
|
InOut.NET wrote: The keyword declares a variable that's accessible by other processes
I'm going to respectfully disagree.
While volatile tells the compiler that variable may be changed by an external "process"
(something going on outside the scope of the variable like another thread, etc.) I don't
believe it makes a variable accessible by other executing processes.
Mark
Mark Salsbery
Microsoft MVP - Visual C++
This episode brought to you by the number 3
|
|
|
|
|
You're probably right.
It does seem a bit far-fetched that another EXE can change your variable.
|
|
|
|
|
InOut.NET wrote: It does seem a bit far-fetched that another EXE can change your variable.
In Windows, yes. On other systems it's entirely possible
Mark
Mark Salsbery
Microsoft MVP - Visual C++
This episode brought to you by the number 3
|
|
|
|
|
I'm working on a program that requires a system tray icon, as it exists almost entirely in the background. I've been working off of the MSDN documentation, and I can get a tray icon to appear when I run the program. However, the window I gave doesn't receive any messages from the icon - I tried putting a call to Beep() in there just to see if it even got to that point, and nothing happens.
Here is the important parts of my code:
<br />
#define MSG_STATUSICON (WM_USER + 101)<br />
<br />
...<br />
<br />
<br />
NOTIFYICONDATA request;<br />
request.cbSize = sizeof(NOTIFYICONDATA);<br />
request.hWnd = HiddenWindow;<br />
request.uID = 0;<br />
request.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICONSCREEN_SMALL));<br />
strcpy((char *)&request.szTip, "Screen Monitor");<br />
request.uCallbackMessage = MSG_STATUSICON;<br />
request.uFlags = NIF_ICON | NIF_TIP | NIF_MESSAGE;<br />
<br />
<br />
BOOL result;<br />
result = Shell_NotifyIcon(NIM_ADD, &request);<br />
if (result != TRUE) {<br />
<br />
return -1;<br />
}<br />
<br />
...<br />
<br />
<br />
case WM_STATUSICON:<br />
<br />
switch (lParam) {<br />
case WM_RBUTTONUP:<br />
<br />
TaskbarIcon::ShowPopupMenu();<br />
break;<br />
case WM_CONTEXTMENU:<br />
<br />
TaskbarIcon::ShowPopupMenu();<br />
break;<br />
default:<br />
break;<br />
}<br />
return 0;<br />
break;<br />
So, yeah. I've told it that I'm using a message ID equal to WM_USER + 101, and I'm checking for that in the callback, but I'm not getting any messages when I right-click the icon. Any ideas?
|
|
|
|
|
|
No... I'm not using MFC, just the Windows API. Thanks, though.
|
|
|
|
|
I'm not sure if it will make a difference but you might need to set the flags BEFORE you set the other data..? (as in put it after the uID parameter). I've got some code which I have used for this sort of thing and it's pretty much identical to yours' apart from that..
If this doesnt work, try getting rid of the icon and tooltip for now and see if the icon actually processes and sends any messages..
Hope this helps!
--PerspX
"Nowadays, security guys break the Mac every single day. Every single day, they come out with a total exploit, your machine can be taken over totally. I dare anybody to do that once a month on the Windows machine." - Bill Gates
|
|
|
|
|
No, that doesn't help - I'm still not receiving any messages, even when I take away the icon and tip. Thanks for the advice, though... it's unusual how code that's so similar isn't working. I'm updating my Platform SDK, so maybe that will help... I wish I had something better than dialup
|
|
|
|
|
... yes it is odd.. are you using Visual Studio?
--PerspX
"Nowadays, security guys break the Mac every single day. Every single day, they come out with a total exploit, your machine can be taken over totally. I dare anybody to do that once a month on the Windows machine." - Bill Gates
|
|
|
|
|
The only thing I see missing is
request.uID = IDI_ICONSCREEN_SMALL; //instead of 0
Also make sure you're looking for MSG_STATUSICON in your message loop, and when you process that
message, the MSG.lParam is what you should switch() on (as shown in your code). You may already
be doing that, but you didn't show it in your code above.
Mark
Mark Salsbery
Microsoft MVP - Visual C++
This episode brought to you by the letter Z
|
|
|
|
|
jamestheprogrammer wrote: #define MSG_STATUSICON (WM_USER + 101)
My first suggestion is to change this to WM_APP instead of WM_USER. WM_USER is used internally by various Win32 controls and I'm seen some weird bugs when those controls are used on the same window as one that processes your own WM_USER message. This probably isn't your problem, but I hate seeing WM_USER used when WM_APP exists and is guaranteed to be unique in your app.
Looking in some code of mine where I have a service displaying a tray icon, I also set the version number in the notify request structure
Here's my entire "create the tray icon" routine that is called from within my interactive service.
if (CreateEx (0, AfxRegisterWndClass (0), "", WS_POPUP, 0, 0, 10, 10, NULL, 0) == 0)
{
return false;
}
m_notifyIconData.cbSize = sizeof (NOTIFYICONDATA);
m_notifyIconData.hWnd = m_hWnd;
m_notifyIconData.uID = 1;
m_notifyIconData.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
m_notifyIconData.uCallbackMessage = WM_APP;
m_notifyIconData.hIcon = ::LoadIcon (AfxGetResourceHandle (),
MAKEINTRESOURCE (IDI_ICONTRAY));
m_notifyIconData.uVersion = NOTIFYICON_VERSION;
strcpy_s (m_notifyIconData.szTip, 64, "xxx Service");
if (Shell_NotifyIcon (NIM_ADD, &m_notifyIconData) == FALSE)
{
return false;
}
m_notifyIconData is a variable of type NOTIFYICONDATA that I keep around so that the service can destroy the icon later if it wants. m_hWnd is the handle created by the CreateEx call.
Hope this helps
Judy
|
|
|
|
|
Yeah, I'm thinking that the problem has something to do with the uVersion variable... I'm actually stuck with VC6 for the time being, and the Platform SDK I have is so old that the uVersion variable doesn't even exist. I'm downloading the February 2003 Platform SDK, so hopefully that will help.
Thanks.
|
|
|
|
|
jamestheprogrammer wrote: I'm thinking that the problem has something to do with the uVersion variable
That's only used when sending a NIM_SETVERSION (via Shell_NotifyIcon), not for NIM_ADD.
Mark
Mark Salsbery
Microsoft MVP - Visual C++
This episode brought to you by the number 3
|
|
|
|
|
You're not receiving any messages from the icon, right?
In your code you show
/* in the callback for HiddenWindow */
...
What is the callback? You should be looking for the MSG_STATUSICON message in the windowproc for
the HWND passed to Shell_NotifyIcon().
LRESULT CALLBACK MyWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (MSG_STATUSICON == uMsg)
{
UINT IconID = (UINT)wParam;
switch((UINT)lParam)
{
case WM_RBUTTONUP:
...
case WM_CONTEXTMENU:
...
case WM_LBUTTONDBLCLK:
...
case WM_LBUTTONDOWN:
...
case WM_RBUTTONDOWN:
...
default:
...
}
}
...
}
Mark
Mark Salsbery
Microsoft MVP - Visual C++
This episode brought to you by the number 3
|
|
|
|
|
Yeah, I think so (unless there's something I'm missing). I've created a Window class called SMStatusHelper, with lpfnWndProc set to the callback in the code I first posted.
<br />
<br />
WNDCLASSEX wndClass;<br />
wndClass.cbSize = sizeof(WNDCLASSEX); wndClass.style = CS_DBLCLKS; <br />
wndClass.lpfnWndProc = WndProc; <br />
wndClass.cbClsExtra = 0; <br />
wndClass.cbWndExtra = 0; <br />
wndClass.hInstance = hInstance; <br />
wndClass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICONSCREEN));<br />
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);<br />
wndClass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);<br />
wndClass.lpszMenuName = NULL;<br />
wndClass.lpszClassName = "SMStatusHelper";<br />
wndClass.hIconSm = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICONSCREEN_SMALL));<br />
RegisterClassEx(&wndClass);<br /> Then I create a new window using the SMStatusHelper class, WS_EX_TOOLWINDOW extended style, and WS_POPUP|WS_VISIBLE for the regular style, using the CreateWindowEx method. I take the return value of that and set it to a global variable called HiddenWindow, which is the hWnd value of the NOTIFYICONDATA structure I pass to Shell_NotifyIcon. So I'm pretty sure that's the right callback...
Thanks.
|
|
|
|