|
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
|
|
|
|
|
You should be able to use either the [] operator or write it as *(myVar + index) -- where myVar is the array and index is the number of the element you want to view.
If you need/want to see the entire array, you might want to open a file and have its output saved to it at various points in time.
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
|
|
|
|
|
Zac Howland wrote: use either the [] operator or write it as *(myVar + index)
and
Zac Howland wrote: want to see the entire array, you might want to open a file
I need the entire array at once, preferably in a file, but I'd like to get it without adding more code to the app.
Another CP user mentioned the myArray,300 notation which display the first 300 members of an array. That should work if I can find a way to capture that to a file.
'til next we type...
HAVE FUN!! -- Jesse
|
|
|
|
|
You can enter the address of the start of the array in the memory window, then cycle through the display formats with Alt+F11 until you come to the right one (there are 14 views - just try them until you see double values )
--Mike--
Visual C++ MVP
LINKS~! Ericahist | PimpFish | CP SearchBar v3.0 | C++ Forum FAQ
|
|
|
|
|
I think I got writing the files to the database to work it taking the file out which seems to be the problem. It doesn't give me any errors after the write and when I look into the database I see that a row was correctly inserted and I see under the file field (OLE Object Type) it says "Long binary data". Here is the code I use for that...
struct RS_FILE
{
long m_l_FileID;
CString m_cs_FileName;
CLongBinary m_lb_FileData;
Any Ideas?
bool DB_File_Insert(CDatabase* db, RS_FILE& rs_file, const std::string& s_file_fullname, CErrorHandler& eh)
{
bool b_ret = true;
HGLOBAL hGlobal = NULL;
try
{
CRecordSetFile rs(db);
if (rs.Open() == FALSE)
{
eh.Initialize();
eh.Set(__FUNCTION__,__FILE__,__LINE__,EHTYPE_ERROR,"Failure to open the file record set to insert a new record.");
return false;
}
rs.AddNew();
rs.m_rs_file = rs_file;
CFile cf;
CFileStatus fileStatus;
if (cf.Open(s_file_fullname.c_str(), CFile::modeRead) == FALSE)
{
eh.Initialize();
eh.Set(__FUNCTION__,__FILE__,__LINE__,EHTYPE_ERROR,"Failure to open the file '%s' for inserting into the database.",s_file_fullname.c_str());
b_ret = false;
goto LabelRecordSetFileClose;
}
if (cf.GetStatus(fileStatus) == FALSE)
{
eh.Initialize();
eh.Set(__FUNCTION__,__FILE__,__LINE__,EHTYPE_ERROR,"Failure to get the status of the file '%s' after opening it to insert into the database.",s_file_fullname.c_str());
b_ret = false;
goto LabelFileClose;
}
rs.m_rs_file.m_cs_FileName = cf.GetFileName();
rs.m_rs_file.m_lb_FileData.m_dwDataLength = fileStatus.m_size;
hGlobal = GlobalAlloc(GPTR,fileStatus.m_size);
if (hGlobal == NULL)
{
eh.Initialize();
eh.Set(__FUNCTION__,__FILE__,__LINE__,EHTYPE_ERROR,"Failure to allocate the specified number of bytes '%ld' for copying the file '%s' into for storing into the database.",fileStatus.m_size,s_file_fullname.c_str());
b_ret = false;
goto LabelFileClose;
}
rs.m_rs_file.m_lb_FileData.m_hData = GlobalLock(hGlobal);
cf.ReadHuge(rs.m_rs_file.m_lb_FileData.m_hData,fileStatus.m_size);
rs.SetFieldDirty(&rs.m_rs_file.m_lb_FileData, TRUE );
rs.SetFieldNull(&rs.m_rs_file.m_lb_FileData, FALSE );
if (rs.Update() == FALSE)
{
eh.Initialize();
eh.Set(__FUNCTION__,__FILE__,__LINE__,EHTYPE_ERROR,"Failure to insert the new record into the database.");
b_ret = false;
}
GlobalUnlock(hGlobal);
LabelFileClose:
cf.Close();
LabelRecordSetFileClose:
rs.Close();
}
catch(CDBException* e1)
{
eh.Initialize();
eh.Set(__FUNCTION__,__FILE__,__LINE__,EHTYPE_ERROR,"Database Error: %s",e1->m_strError);
return false;
}
catch(CException* e2)
{
eh.Initialize();
char sz_error [MAX_PATH] = "";
e2->GetErrorMessage(sz_error,sizeof(sz_error));
eh.Set(__FUNCTION__,__FILE__,__LINE__,EHTYPE_ERROR,"Database Error: %s",sz_error);
return false;
}
catch(...)
{
eh.Initialize();
eh.Set(__FUNCTION__,__FILE__,__LINE__,EHTYPE_ERROR,"Database Error: Unknown.");
return false;
}
return b_ret;
}
Now here it the code where I try to get the file and write it to a folder....
bool DB_File_GetID(CDatabase* db, const long& l_id, RS_FILE& rs_file, CErrorHandler& eh)
{
try
{
CRecordSetFile rs(db);
rs.m_strFilter.Format("[FileID] = %ld",l_id);
if (rs.Open() == FALSE)
{
eh.Initialize();
eh.Set(__FUNCTION__,__FILE__,__LINE__,EHTYPE_ERROR,"Failure to open the record set to get the file id '%ld'.",l_id);
return false;
}
rs_file = rs.m_rs_file;
rs.Close();
}
catch(CDBException* e1)
{
eh.Initialize();
eh.Set(__FUNCTION__,__FILE__,__LINE__,EHTYPE_ERROR,"Database Error: %s",e1->m_strError);
return false;
}
catch(CException* e2)
{
eh.Initialize();
char sz_error [MAX_PATH] = "";
e2->GetErrorMessage(sz_error,sizeof(sz_error));
eh.Set(__FUNCTION__,__FILE__,__LINE__,EHTYPE_ERROR,"Database Error: %s",sz_error);
return false;
}
catch(...)
{
eh.Initialize();
eh.Set(__FUNCTION__,__FILE__,__LINE__,EHTYPE_ERROR,"Database Error: Unknown.");
return false;
}
return true;
}
bool RS_FILE::WriteFile(const std::string& s_folder, CErrorHandler& eh)
{
std::string s_temp_folder = s_folder;
if(s_temp_folder.length() == 0)
{
eh.Initialize();
eh.Set(__FUNCTION__,__FILE__,__LINE__,EHTYPE_ERROR,"Failure to write the file to a folder because the folder is not specified.");
return false;
}
if (s_temp_folder[s_temp_folder.length()-1] != '\\')
s_temp_folder += "\\";
std::string s_file = ssprintf("%s%s",s_temp_folder.c_str(),m_cs_FileName);
CFile cf;
if (cf.Open(s_file.c_str(),CFile::modeCreate|CFile::modeWrite) == FALSE)
{
eh.Initialize();
eh.Set(__FUNCTION__,__FILE__,__LINE__,EHTYPE_ERROR,"Failure to open and create the file '%s' to write data to.",s_file.c_str());
return false;
}
LPSTR buffer = (LPSTR)GlobalLock(m_lb_FileData.m_hData);
cf.WriteHuge(buffer,m_lb_FileData.m_dwDataLength);
GlobalUnlock(m_lb_FileData.m_hData);
cf.Close();
return true;
}
The failure is occurring in the CFile look below....
void CFile::Write(const void* lpBuf, UINT nCount)
{
ASSERT_VALID(this);
ASSERT(m_hFile != (UINT)hFileNull);
if (nCount == 0)
return;
ASSERT(lpBuf != NULL);
Any help is greatly appreciated. I know this post is a little long be I am not sure where the error is.
Chris
|
|
|
|
|