Really shameless pointer abuse

Posted on 2007-10-10
Last Modified: 2013-11-20
OK, this one's gonna be difficult to explain, but I'll do my best . . .

My company writes bank software.  The software has a marketing programs feature which will pop up a marketing program eligibility dialog to the teller when they pull up a customer's account.  The teller pitches the program to the customer, and has the option to click accept, decline, or follow-up.  If the teller clicks accept or follow-up, the program creates a sales lead in the system.  Later on, when a branch manager is reviewing the sales leads, he/she can add notes to each one if they wish.

Right now I am working to extend this feature so that the teller can also enter notes while the lead is being generated.  It has to be on the marketing popup, because tellers do not have access to the sales leads screen, and once the teller hits accept or follow-up, the box goes away.

The goal here is to simply recycle the the notes dialog from the sales lead screen.  But since I can't add a note to a sales lead that doesn't exist yet, I have to call the notes dialog, "steal" the info out of it so it can be bent to my own evil desires, and then kill it before the code to add the note to the database gets executed (which is easily accomplished by having the notes dialog end if the sales lead ID is -1).  When the teller hits accept, then the marketing popup is supposed to create the new sales lead, get the ID, and then attach the note to it all in one shot.

So here's what I've attempted to do:
I added an "Add Note..." button and gave the marketing popup a CEdit *noteTextBox member.  Then, I call the notes dialog and pass it the address of the noteTextBox member (&noteTextBox) to its Init() function (which I extended to accept a pointer to a CEdit box as one of its arguments).

Now, when the Init() function of the notes dialog runs, it takes the address of its own CEdit box (which is already defined), and assigns it to the reference it got from the marketing popup.  The function looks like this:

... in the marketing popup,
CEdit noteTextBox
NotesDialog notesDlg;

.. in the notes dialog,
NotesDialog::Init(CEdit *pNotesTextBox)
   pNotesTextBox = &m_notesEdit; //m_notesEdit is a private CEdit object

By my reasoning, the marketing popup's edit box should now be pointing to the same place as the notes dialog's edit box, right?  Furthermore, changes in the notes dialog's edit box should be automatically visible from the marketing popup, right??

Well, as soon as the marketing popup does a notesTextBox.GetWindowText(string), the program pukes with a debug assertion error.  I'm not sure why, but I have a few theories:

- The note dialog's m_notesEdit member is private and I am violating encapsulation (this means the compiler is smarter than I am, yet still not smart enough to warn me about it).
- The pointer is getting mangled somehow between the two objects (one's a CEdit, and the other's a CEdit*)
- At some point before I do the GetWindowText(), the notes dialog is being destroyed (along with all its members), making the pointer no longer valid.  Does EndDialog() call the destructor?
- My thinking is totally wrong.  It's completely insane to have two members from different objects pointing to the same place and I should try doing this some other way.
- A fifth option which I haven't considered

Anyone have any ideas as to what's going wrong here and how to fix it?  It would be very much appreciated.  If you can help me out with this, then me luv u long time!
Question by:cuziyq
    LVL 43

    Expert Comment

    NotesDialog notesDlg;

    I suspect the window object has not been created when you are calling GetWindowText
    LVL 39

    Expert Comment

    CEdit noteTextBox;
    With that you get a MFC edit control object but not a window

    >>>> NotesDialog notesDlg;
    With that you get a MFC dialog object but not a window.

    >>>> notesDlg.Init(&noteTextBox)
    With that you passing the address of a - not created - edit control object to a function.

    >>>> pNotesTextBox = &m_notesEdit;
    That assigns a different address value to the local pointer. As the pointer wasn't returned the assignment ... makes nothing.

    Regards, Alex
    LVL 39

    Accepted Solution

    >>>> By my reasoning, the marketing popup's
    >>>> edit box should now be pointing to the same
    >>>> place as the notes dialog's edit box, right?
    No, you passed a pointer (value) to a function but overwrites the value locally with a different pointer value.

    If you want get the address of a edit control you need to pass the pointer by reference:

       void NotesDialog::Init(CEdit*& pNotesTextBox)  // see the &

    That means the address assigned in NotesDialog::Init was passed back to the caller. if doing so

        CEdit noteTextBox;
        NotesDialog notesDlg;

    the last statement wouldn't compile cause you can't pass the address of a locally defined object as a (writeable) reference to another function. And of course, you don't need the local 'noteTextBox' object. You want the address to the edit control defined in the NotesDialog, right? Then, you need:

        CEdit* pnoteTextBox = NULL;   // define a pointer not an object
        NotesDialog notesDlg;
        notesDlg.Init(pnoteTextBox);  // now you get the pointer filled
                                                        // with the address of the notesDlg.m_edit

    But still we have

    - a not-created NotesDialog
    - therefore a pointer to an edit control which was not created either

    So, you would need to 'create' the notesDlg. The easiest to do so, is


    but unfortunately that means you are passing modal control to the notesDlg and your current dialog was blocked until the NotesDlg was finished (Cancel or OK). I don't think that is what you want. I neither think that you are supposed to create a 'new' NotesDialog but 'hook' into an existing NotesDialog which was invoked by another App. Am I right or is there any other scenario?

    Regards, Alex

    LVL 14

    Author Comment

    Thanx, Alex.  I appreciate your knowledgeable reply.  Unfortunately, after I went the rest of the afternoon with no response, I decided to change tactics a little.  I made the add notes button a check box instead.  That way, the marketing popup can just look at the checkbox after it has already added the sales lead to the database, allowing the notes dialog to process normally.  This approach has a couple of slight drawbacks (none of which I can really explain without writing another book on the subject), but they were deemed to not be a big deal by the powers that be.

    I will give you the points anyway because your response was informative.  I would love to explore it further, because I still believe the concept is valid (just my implementation was off).  But to tell you the truth, the feature is finished now and I'm just not that motivated to mull it over anymore.  LOL.  The idea seems useful, however, and I will probably give it another attempt in the future when working on something else.  Maybe we can hash it over when that time comes.

    Thanks again.

    Write Comment

    Please enter a first name

    Please enter a last name

    We will never share this with anyone.

    Featured Post

    Threat Intelligence Starter Resources

    Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

    Suggested Solutions

    This is to be the first in a series of articles demonstrating the development of a complete windows based application using the MFC classes.  I’ll try to keep each article focused on one (or a couple) of the tasks that one may meet.   Introductio…
    Introduction: Load and Save to file, Document-View interaction inside the SDI. Continuing from the second article about sudoku.   Open the project in visual studio. From the class view select CSudokuDoc and double click to open the header …
    This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
    Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…

    737 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    18 Experts available now in Live!

    Get 1:1 Help Now