Archived

This forum has been archived. Please start a new discussion on GitHub.

Proper Cleanup in an MFC Application

I have the following code:
#include "StdAfx.h"
#include "servant.h"

#include "pdfrendererI.h"

#include <Ice/Ice.h>

#include <string>

using namespace std;

cservant::cservant() {
	Ice::ObjectAdapterPtr adapter;
	try {
		communicator = Ice::initialize(__argc, __argv);
		adapter = communicator->createObjectAdapter("Renderer");
		PDFRenderer::RendererPtr rendererObject = new PDFRenderer::RendererI();
		adapter->add(rendererObject, communicator->stringToIdentity("renderer"));
		adapter->activate();
	} catch (Ice::Exception &e) {
        ostringstream ostr;
        ostr << e;
        string s = ostr.str();
        AfxMessageBox(CString(s.c_str()), MB_OK|MB_ICONEXCLAMATION);
	}
}

cservant::~cservant() {
	communicator->shutdown();
	communicator->destroy();
}

When I compile this, it compiles fine. When I close the application, the dtor is called as expected, but VC2005 emits a bunch of data, preceeded by "Detected memory leaks!".

What objects do I need to explicitly destroy and in what order as to not have any memory leaks?

Comments

  • matthew
    matthew NL, Canada
    Have you looked at the MFC demos in the Ice distribution? These do not contain any memory leaks. Note that even if you clean up correctly you may see these messages -- see http://www.zeroc.com/vbulletin/showthread.php?t=701 for more details.

    I recommend using a real leak detection tool such as purify. The leak checker in MFC is all but useless.
  • How to cancel long-running request

    Matthew,
    I've consulted all your published articles in respect to Integrating Ice with a GUI(Connections #12-15), and would like to ask you a question: how to solve the problem of a long-running request graceful cancellation.
    You may think of a request as a SQL-like statement, which server translates and executes against database. So user may want to cancel the long-running operation not having to wait for a result, in order to abort the "ill-formed statement" execution, and not terminating UI. What do you think would be the best strategy for this kind of scenario?

    If possible, It would be very helpful to have a sample MFC application within Ice distribution package or thread-related download demonstrating such solution.
    Thank you
  • matthew
    matthew NL, Canada
    It depends what you want to do :)

    For example, lets say you want to have a progress bar in the status bar of your app and a cancel button to the left of this progress bar. When cancel is pressed the simplest thing to do is to mark the request as canceled, and ignore the result when it arrives. However, if you actually want to cancel the request on the server-side, this requires more work (and may be impossible).

    If you let me know exactly what you want to accomplish I can help you work out the best way to do it.
  • To cancel request on the server-side as well

    Matthew,
    Thanks for your reply,
    To be able to cancel request on the server-side - that's exactly what I want to accomplish. Again, if you think of the request as a possibly ill-formed SQL-like statement, going down the road against distributed multi-partitioned database, you do not want user to be: 1) waiting response for a long time('ok' request may take, let's say 10 mins); 2)able to cancel the request on the server(s), so database won't be down; 3)give client and middleware tier a chance to cleanup gracefully.
    So, the task at hands is to be able to send a "cancel request" msg to the server from the MFC-based GUI, and, let's say, continue modifying the request. Just ignoring the response on the client side can be very expansive for the overall architecture.
    I guess it's going to be an interesting challange..
    Thank you in advance
    Yuri
  • matthew
    matthew NL, Canada
    The question then comes down to whether you can cancel the outstanding SQL request. If you can, then its possible to do what you want. If you cannot, then you are out of luck.
  • Let's say Yes, it's possible to kill the thread by request message uid on the middleware level, remove the item from the messaging bus (java-written), and at least let the database handle the rest on its own (not much we can do about it..)
    Assuming, the GUI client talks to the server, which receives request and pushes it to the middleware for processing, then receives the response and returns it back to the client, what do you think would be the best strategy to handle cancellation on the client-server level? (it will then let server to propagete the 'cancel request' message down to the messaging system)
    Thank you, Matthew
  • matthew
    matthew NL, Canada
    At the most basic level you need some method to associate the running request in the server with the request you made in the client. I can think of a few ways of doing this. For example:

    - You pass a request id with each query. Add a method to the query interface to cancel a request with a given id.
    - If you only allow one outstanding query in the client it becomes much simpler, since then you only need "cancel" to cancel the last query (and don't need an explicit request id).

    You could also re-arrange your interfaces so that you pass in a notification object to the request which is called with the results, and a control object is passed back to the caller which can be used to cancel the request. This would be similar to what we do automatically with AMI/AMD. Something like:
    interface Query
    {
        StringSeq someLongRunningQuery();
    };
    

    Becomes:
    interface LongRunningQueryResults
    {
        void results(StringSeq data);
    
    };
    
    interface QueryControl
    {
        void cancel();
    };
    
    interface Query
    {
        QueryControl* someLongRunningQuery(LongRunningQueryResults* callback);
    };
    

    When you make the request in the server you need to put whatever information that is necessary to actually perform the cancelation in some data structure. When you receive the cancelation request, then you do whatever you need to do to unblock the actual thread that is running the request and return. In the thread running the request presumably the database query will then unblock, and you can throw some exception to indicate that the query was canceled.
  • Matthew,
    How about GUI? AMI interface is that's what we can use, but for non-blocking UI - what is the best strategy? Would it be OK to use AMI and calling queue technics described in issues 12-13 of Connections, for this kind of scenario?
    Thanks
  • matthew
    matthew NL, Canada
    AMI should work just fine... How exactly you call these interfaces is irrelevant.
  • Thanks Matthew,
    Back to your first response: Can you give me a hint: how can I propagate, or StepIt(), the progress bar for the long-running request with AMI approach?
    And also can AMI work for web (.NET GUI) client as well?
  • marc
    marc Florida
    You could create a thread that shows the progress bar or use any other means to show a progress bar for the timeout you have chosen. This really doesn't have anything to do with Ice (or with AMI), but this is GUI programming in general.

    If you would like us to provide you with consulting services to help you with the design of your application, please contact us at info@zeroc.com. Giving general design advice is out of the scope of the free support we can provide here on these forums.
  • You are right, Marc.. Thanks
    Matthew, back to my last question: Can AMI approach work for web (.NET GUI) client as well?
    Again, thank you for your help
  • matthew
    matthew NL, Canada
    The AMI interface is fully supported in C#, so in theory it should work.