CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 12 of 12
  1. #1
    Join Date
    Dec 2008
    Posts
    8

    MFC ListBox problem

    I am trying to create my own listbox class but failed. Here is the source code:

    // MyListBox.h
    Code:
    class CMyListBox : public CListBox
    {
    	DECLARE_DYNAMIC(CMyListBox)
    
    public:
    	CMyListBox(void);
    	virtual ~CMyListBox(void);	
    	int AddDetailedString(const LPCTSTR lpszItem, const CString csDetail);
                     ...
    private:
    	CObArray				m_coDetails;
    };
    // MyListBox.cpp
    Code:
    IMPLEMENT_DYNAMIC(CMyListBox, CDialog)
    
    CMyListBox::CMyListBox(void) {}
    
    CMyListBox::~CMyListBox(void) {}
    
    int CMyListBox::AddDetailedString(const LPCTSTR lpszItem, const CString csDetail)
    {
    	LPCTSTR lpszDetail = csDetail;
    	m_coDetails.Add((CObject*)lpszDetail); // this line always crash
    	return CListBox::AddString(lpszItem);
    }
    I have no idea why if I delcared a private array (or vector) variable and then push the elements to it. It always crash! If I use CObArray, I got "privileged instruction" promopt and debugger run at "AfxAssertValidObject". If I use std::vector, I got "Access Violation" and debugger run at "CheckBytes".

    Please could anyone give me some suggestion to solve this problem?

    Many thanks!
    Last edited by chesschi; December 7th, 2011 at 12:22 PM.

  2. #2
    Join Date
    Aug 2000
    Location
    West Virginia
    Posts
    7,721

    Re: MFC ListBox problem

    This is a guess, since I am not familiar with CObarray, but ...
    Code:
    LPCTSTR lpszDetail = csDetail;
    m_coDetails.Add((CObject*)lpszDetail); // this line always crash
    I am not sure that forcing a non-CObject pointer to a CObject pointer is valid.
    Also, there could be scoping problems.

    Why not make m_coDetails a CStringArray (or equivalent) ?

  3. #3
    Join Date
    Dec 2008
    Posts
    8

    Re: MFC ListBox problem

    Basically any container like vector or CStringArray will crash

  4. #4
    Join Date
    Sep 2004
    Location
    Holland (land of the dope)
    Posts
    4,123

    Re: MFC ListBox problem

    Quote Originally Posted by chesschi View Post
    Basically any container like vector or CStringArray will crash
    To start with, you are trying to store a variable from the function stack in a list. So, as long as the list that you are using doesn't make a copy of the object, storing it is useless. After the function ends, the stored object in the list will be destroyed. Also, if you run your program in the debugger, the debugger wil stop at the point of the crash and you can see why it crashes.

  5. #5
    GCDEF is offline Elite Member Power Poster
    Join Date
    Nov 2003
    Location
    Florida
    Posts
    12,635

    Re: MFC ListBox problem

    Is it crashing or tripping an ASSERT?

    CString is not derived from CObject.

    A CStringArray will work, or why not just use the CListBox SetItemData() or SetItemDataPtr() functions?
    Last edited by GCDEF; December 7th, 2011 at 12:39 PM.

  6. #6
    Join Date
    Apr 1999
    Posts
    27,449

    Re: MFC ListBox problem

    Quote Originally Posted by chesschi View Post
    I have no idea why if I delcared a private array (or vector) variable and then push the elements to it. It always crash!
    That is exactly the reason why it crashes -- it is "private" or local to the function. When that function returns, that local variable no longer exists.

    I'll add to what Skizmo stated:

    1) You are storing a pointer in the CObArray. OK, a CObArray can contain pointers, so it looks like it works.

    2) Now, that pointer you're storing points to the internal CString you passed in (actually the buffer of characters). So you have a pointer to the CString buffer being placed in the CObArray.

    3) That CString is a parameter that was passed by value. Passing by value means that the CString parameter is temporary. When that function exits, that CString is gone down the drain and no longer exists.

    Now, do you see why it crashes? That pointer doesn't point to anything valid when that function exits. The CString that was passed in has disappeared into thin air when that function returns. The data that is in the CString no longer is valid. So your container now has a bad pointer within it.
    If I use CObArray, I got "privileged instruction" promopt and debugger run at "AfxAssertValidObject". If I use std::vector, I got "Access Violation" and debugger run at "CheckBytes".
    All explained above.
    Please could anyone give me some suggestion to solve this problem?
    My suggestion is to study up on scope, object lifetimes, etc. The issue has nothing to do with CObArray or vector, and has everything to do with not understanding fully how C++ works with respect to functions, variables, and scope. Unless you know these topics, you'll make this same mistake again, and the bad part is that you may not know you've made this mistake until your program is running on someone else's machine and crashes at random times.

    Bottom line is that if you're going to store pointers to things in containers such as CObArray or vector, that thing you're pointing to has to be still "alive" when you access it later on.

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; December 7th, 2011 at 01:15 PM.

  7. #7
    GCDEF is offline Elite Member Power Poster
    Join Date
    Nov 2003
    Location
    Florida
    Posts
    12,635

    Re: MFC ListBox problem

    I don't think that's the problem Paul. The pointer is still in scope at the time he adds. I'm pretty sure he's casting an CString to a CObject and getting an ASSERT or maybe a crash because he's casting a CString to something it's not.

    Regardless, I think it's probably moot as the List Box already has the ability to store pointers built in.

    Also, to the OP, are you considering the sort order of your list box?
    Last edited by GCDEF; December 7th, 2011 at 01:23 PM.

  8. #8
    Join Date
    Apr 1999
    Posts
    27,449

    Re: MFC ListBox problem

    Quote Originally Posted by GCDEF View Post
    I don't think that's the problem Paul. The pointer is still in scope at the time he adds. I'm pretty sure he's casting an CString to a CObject and getting an ASSERT or maybe a crash because he's casting a CString to something it's not.
    OK. I was looking at the issue differently -- after that function exits. If the OP attempts to do anything with the CObArray, even if that line didn't crash right away, the program is still accessing an invalid pointer.

    So there are two problems, the immediate one, and one that would have occurred later on if the first one didn't trip the ASSERT().

    Regards,

    Paul McKenzie

  9. #9
    GCDEF is offline Elite Member Power Poster
    Join Date
    Nov 2003
    Location
    Florida
    Posts
    12,635

    Re: MFC ListBox problem

    Quote Originally Posted by Paul McKenzie View Post
    OK. I was looking at the issue differently -- after that function exits. If the OP attempts to do anything with the CObArray, even if that line didn't crash right away, the program is still accessing an invalid pointer.

    So there are two problems, the immediate one, and one that would have occurred later on if the first one didn't trip the ASSERT().

    Regards,

    Paul McKenzie
    Yeah, your point is still valid and still waiting for him. A CStringArray will make both problems go away, assuming he really needs one.

  10. #10
    Join Date
    Dec 2008
    Posts
    8

    Re: MFC ListBox problem

    Quote Originally Posted by Paul McKenzie View Post
    That is exactly the reason why it crashes -- it is "private" or local to the function. When that function returns, that local variable no longer exists.
    Thanks Paul. You are right. Actually I am implementing my own tab control and use a CObArray container to store any listbox, button, edit box, etc...

    And I use tabCtrl.GetDlgItem(IDC_LISTBOX_XXX) to get my own list box control (not via COBArray). Although the debugger shows an assertion at the point I am stepping through at this line
    Code:
    m_coDetails.Add((CObject*)lpszDetail);
    and before the line
    Code:
    return CListBox::AddString(lpszItem);
    .
    I believe it could be the problem that the MS Visual Studio compiler is unable to catch that. It is because, as you mentioned, if I use any private member (e.g. CString, CStringArray, vector, etc...) it will also get the assertion.

    Cheers~~!

  11. #11
    Join Date
    Feb 2003
    Location
    Iasi - Romania
    Posts
    8,234

    Re: MFC ListBox problem

    Always store in a CObArray pointers to CObject-derived objects.
    Not LPCTSTR, not CString, not CStringArray...
    If you want any type of pointers, use CPtrArray.
    Ovidiu
    "When in Rome, do as Romans do."
    My latest articles: https://codexpertro.wordpress.com/

  12. #12
    GCDEF is offline Elite Member Power Poster
    Join Date
    Nov 2003
    Location
    Florida
    Posts
    12,635

    Re: MFC ListBox problem

    Quote Originally Posted by chesschi View Post
    Thanks Paul. You are right. Actually I am implementing my own tab control and use a CObArray container to store any listbox, button, edit box, etc...

    And I use tabCtrl.GetDlgItem(IDC_LISTBOX_XXX) to get my own list box control (not via COBArray). Although the debugger shows an assertion at the point I am stepping through at this line
    Code:
    m_coDetails.Add((CObject*)lpszDetail);
    and before the line
    Code:
    return CListBox::AddString(lpszItem);
    .
    I believe it could be the problem that the MS Visual Studio compiler is unable to catch that. It is because, as you mentioned, if I use any private member (e.g. CString, CStringArray, vector, etc...) it will also get the assertion.

    Cheers~~!
    As I've been telling you, the ASSERT is likely because CString is not derived from CObject*.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured