|
CDriver is defined in a library (.lib) file that statically linked at compilation. I'm pretty sure its loading the correct lib file, but I'll double check.
|
|
|
|
|
Is the destructor in CDriver declared as virtual?
If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week
Zac
|
|
|
|
|
No, the destructor is not virtual. Should this be? If so, I guess I've forgotten basic C++ inheritance rules in which my question makes me look silly!!
|
|
|
|
|
Yes. The destructor MUST be declared virtual if you plan to derive from it. Here is why:
class Base
{
public:
Base() {}
~Base() {}
private:
};
class Derived : public Base
{
public:
Derived() {}
~Derived() {}
private:
int m_MyInt;
};
void main()
{
Base* pB = new Derived;
delete pB;
}
What happens is that the ~Base() destructor is called, but not the ~Derived(). Thus, m_MyInt stays allocated in memory (that is, the portion of memory allocated for a Base object is freed, but not that for Derived). This is called memory slicing (see "Effective C++" by Scott Meyers for more details).
The rule of thumb: If your class is meant to have classes derived from it, it MUST have a virtual destructor.
This problem can (and will) blow up your memory eventually (either stack or heap or both).
-- modified at 16:48 Monday 31st July, 2006
If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week
Zac
|
|
|
|
|
Thanks. This was a good catch. Unfortunately, I still get an 'access violation' at destructor. I set a breakpoint in my derived class CMyDriver, and it doesnt step into the CDriver nor IDriver.
I'm just confused. If I remove the member variables from the class definition, things work fine.
|
|
|
|
|
Any way you can actually show the code (slimmed down) you are using? The definitions of all 3 classes and the implementations for the destructors would be helpful in evaluating your problem.
If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week
Zac
|
|
|
|
|
CIDriver, CDriver and CMyDriver all have virtual destructors.
__declspec(dllexport) CIDriver* InitDriver(CIKernel* i_hKernel)
{
//__asm { int 0x03 }
CMyDriver* hUserDriver = new CUserDriver;
hUserDriver->Create(i_hKernel);
return (CIDriver *)hUserDriver;
}
__declspec(dllexport) void EndDriver(CIDriver* i_hIDriver)
{
CMyDriver * hUserDriver = (CMyDriver *)i_hIDriver;
hUserDriver->Destroy();
delete hUserDriver;
}
My app crashes at the 'delete hUserDriver'. EndDriver is an exposed interface call that another DLL calls to detroy the driver. hUserDriver->Destroy() destroy all internal structures of CDriver (not CMyDriver, as this function isnt overloaded in CMyDriver). CMyDriver is not referencing any objects destroyed by the Destroy call. Nothing is available in the debugger as its all assembly at that point.
In the class definition for CMyDriver, if I add public member variables, it crashes on the delete. If I make them global (file scope), it doesnt crash.
I"m wondering if its looking at the class size or something. I'm just confused.
-C
|
|
|
|
|
Wheatbread wrote: CMyDriver * hUserDriver = (CMyDriver *)i_hIDriver;
hUserDriver->Destroy();
delete hUserDriver;
}
My app crashes at the 'delete hUserDriver'. EndDriver is an exposed interface call that another DLL calls to detroy the driver. hUserDriver->Destroy() destroy all internal structures of CDriver (not CMyDriver, as this function isnt overloaded in CMyDriver). CMyDriver is not referencing any objects destroyed by the Destroy call. Nothing is available in the debugger as its all assembly at that point.
Does Destroy get called from any of those destructors (or is anything that is cleaned up in Destroy also cleaned up in any of the destructors)?
Wheatbread wrote: CMyDriver * hUserDriver = (CMyDriver *)i_hIDriver;
Just FYI, this is a dangerous cast. You should use dynamic_cast or reinterpret_cast to do this (and check the return value). This shouldn't be the cause of your problem, though.
If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week
Zac
|
|
|
|
|
Hi,
I am having a trouble with my CListCtrl
I need to get the subitem number.
void CDlg::OnItemchangedList(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW *pNMListView = (NM_LISTVIEW*)pNMHDR;
int nItem = pNMListView->iItem;
int nSubItem = pNMListView->iSubItem;
*pResult = 0;
}
The above is returning the nItem number properly. But it is always giving zero for nSubItem.
Why is this happening?
Thanks.
Tara
Fortitudine Vincimus!
|
|
|
|
|
How many subitems does it have? Can you post the code that you use to add the subitems?
Best wishes,
Hans
|
|
|
|
|
I use SetItemText to add items to the list.
The items are read from mdb database. The number varies from two to about 50.
Fortitudine Vincimus!
|
|
|
|
|
Just respond to the NM_CLICK notification message.
"Money talks. When my money starts to talk, I get a bill to shut it up." - Frank
"Judge not by the eye but by the heart." - Native American Proverb
|
|
|
|
|
I am using CEditList class got from codeproject. I have added a lot of other features to it. There is already an NM_CLICK message handled there. If I try to add one more message in the dialog box class, it does not work. But as such, when I put a message box in the onClick function in CEditList, it correctly gave the column number.
Fortitudine Vincimus!
|
|
|
|
|
|
Why is it that when NM_CLICK message is used, it returns the subitem correctly, but when ItemChanged is used it return only the item number?
Michael Dunn wrote: Subitems don't have their own states, only iItem is relevant for that notification.
...meaning that for ItemChanged notification, only the item number is relevant so the subitem number is not returned?
-- modified at 1:40 Tuesday 1st August, 2006
Fortitudine Vincimus!
|
|
|
|
|
why you dont use from NM_CLICK
|
|
|
|
|
WhiteSky wrote: why you dont use from NM_CLICK
I am using CEditList class got from codeproject. I have added a lot of other features to it. There is already an NM_CLICK message handled there.
If I try to add one more message in the dialog box class, it does not work. But as such, when I put a message box in the onClick function in CEditList, it correctly gave the column number.
I need to get the column number to save the data to the database. Earlier, I was saving the whole list, but this slows the program too much. So if I can get the column no. of the changed item, I will need to only save that item.
Fortitudine Vincimus!
|
|
|
|
|
I got it!
This is what I did:
In OnClick function of CEditList, I added
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
Item =pNMListView->iItem;
subItem =pNMListView->iSubItem;
Then in my dialog class:
void CXBudget::OnItemchangedXBudgetLISTMain(NMHDR* pNMHDR, LRESULT* pResult)
{
nitem = m_XBudgetLIST_Main.Item;
nSubItem = m_XBudgetLIST_Main.subItem;
if (nSubItem >=2)
SaveChanges(nitem,nSubItem);
}
Fortitudine Vincimus!
|
|
|
|
|
Folks,
Using the Visual C++ 6.0 debugger, how can I view (or better, print to file) the contents of an array of doubles? I know I can see the address of the array variable and the contents of the first member element using the Quickwatch or watch window, but I need to examine the entire contents of the array (length ~300 elements). I can't use the TRACE macro because this app does not use MFC (and it's coded in 'C', not C++).
I think I recall a notation style one could type into the QuickWatch window that would do this but I've forgotten it.
TIA!
'til next we type...
HAVE FUN!! -- Jesse
|
|
|
|
|
Just click the '+' sign next to the variable's name. You can also look at individual items using square brackets (e.g., MyArray[2] , MyArray[4] ).
"Money talks. When my money starts to talk, I get a bill to shut it up." - Frank
"Judge not by the eye but by the heart." - Native American Proverb
|
|
|
|
|
Thanks, but I need to see the contents of the entire array at once. Clicking the + only shows the first element because the array variable is really a pointer allocated dynamically.
'til next we type...
HAVE FUN!! -- Jesse
|
|
|
|
|
another approach is operator [] extracted via local variable
Kuphryn
|
|
|
|
|
I'm assuming that your array is allocated with "new", otherwise simply clicking on the + button would expand your entire array.
If that's the case:
double *pMyDouble = new double[300];
then in your watch you can simply use
pMyDouble,300
That will show 300 elements of type double.
Hope that helps.
Karl - WK5M
PP-ASEL-IA (N43CS)
<kmedcalf@ev1.net>
PGP Key: 0xDB02E193
PGP Key Fingerprint: 8F06 5A2E 2735 892B 821C 871A 0411 94EA DB02 E193
|
|
|
|
|
kuphryn wrote: operator []
This application is straight 'C', not C++.
'til next we type...
HAVE FUN!! -- Jesse
|
|
|
|
|
krmed wrote: pMyDouble,300
Aha! You've won yourself a cupie doll! That's the Watch Window notation I had forgotten. Thanks a bunch!
'til next we type...
HAVE FUN!! -- Jesse
|
|
|
|