Archived

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

Error message on "run" exit

At the end of "run" (Within an application derived from Ice::Application).
This application is like your CD example. A single client uses multiple servers to compress an image sequence. An "ami" compress method is called on the servers. At the end of compressing some frames the "run" method reaches the end of an apparently successful encoding job but then:

Debug Assertion Failed!

Program: d:\Valhalla\Windows\Debug\IceEncoderC.exe
File: dbgdel.cpp
Line: 52

Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

Comments

  • marc
    marc Florida
    This is most likely caused by mixing debug and release libraries. Have a look at:

    http://www.zeroc.com/faq/windowsLibraryMixup.html

    And also at this thread:

    http://www.zeroc.com/vbulletin/showthread.php?t=1824
  • Thanks for your response. I think I had it set up properly.
    My current settings:

    Debug configuration: (problem happened here)

    Under "General/Output Directory":
    ..\..\..\..\..\..\Windows\Debug

    Under "C/C++/Code Generation/Runtime Library":
    Multi-threaded Debug DLL (/MDd)

    Under "Linker/Input/Additional Dependicies":
    Iced.lib IceUtild.lib IceGridd.lib $(OutDir)\glib.lib

    Release configuration: (never terminates - my code spins its wheels waiting for last encoders to finish)

    Under "General/Output Directory":
    ..\..\..\..\..\..\Windows\Release

    Under "C/C++/Code Generation/Runtime Library":
    Multi-threaded DLL (/MD)

    Under "Linker/Input/Additional Dependicies":
    Ice.lib IceUtil.lib IceGrid.lib $(OutDir)\glib.lib
  • marc
    marc Florida
    I can't think of any other reason for this error. Every time so far when somebody has encountered this problem, it was a library mix-up.

    If you have a small, self-contained example that demonstrates the problem, we can further investigate.
  • This seems to get past the error, is it right?

    int IceEncoderClient::run (int argc, char *argv[]) {
    AMI_Encoder_compressI reply; // old code
    Ice::ObjectPrx proxy;
    Ice::ObjectProxySeq seq;
    IceGrid::QueryPrx query;

    proxy = communicator()->stringToProxy( "IceGrid/Query");
    query = IceGrid::QueryPrx::checkedCast( proxy);
    type = Encoder::ice_staticId();

    ...

    encoders[ v.i].proxy->compress_async( &reply, strings); // old code
    encoders[ v.i].proxy->compress_async( new AMI_Encoder_compressI, strings);
    }
  • marc
    marc Florida
    This code is wrong:
    AMI_Encoder_compressI reply;
    

    You must not allocate AMI objects on the stack, since these objects are reference counted. Instead, you can use:
    AMI_Encode_compressPtr reply = new AMI_Encode_compressI;
    

    If you do not need to hold on to the reply object, you can also use this:
    encoders[ v.i].proxy->compress_async( new AMI_Encoder_compressI, strings);
    

    If you need access to the derived object, you can use:
    typedef IceUtil::Handle<AMI_Encode_compressI> AMI_Encode_compressIPtr;
    AMI_Encode_compressIPtr reply = new AMI_Encode_compressI;
    
  • Thanks and one more Q

    Hi Marc,

    How many AMI_Encode_compressI objects do I need?
    (1) One?
    (2) One per encode server?
    (3) One per invocation of compress_async?

    Thanks, Larry
  • marc
    marc Florida
    You you need one per concurrent invocation, i.e., you can reuse these objects once the AMI call is finished.
  • Thanks very much

    Thanks Marc
  • Slice classes and servant classes must always be allocated on the heap because, as soon as you pass a Slice class or a servant to an Ice API, a smart pointer to the instance will be constructed. If the instance is allocated on the stack, that will ultimately result in a call to delete for a stack address, which has undefined behavior. (Usually, you get a core dump.)

    It is a good idea to habitually add a protected destructor to servant classes and to the implementation of abstract Slice classes. For example:
    class AMI_Encoder_compressI : public AMI_Encoder_compress {
    public:
        // ...
    protected:
        virtual ~AMI_Encoder_compressI {}
    };
    

    The destructor need not be inline or empty. The only thing that matters is that the destructor is protected. With that, it becomes impossible to accidentally instantiate the class on the heap:
    AMI_Encoder_compressI reply; // Compile-time error
    

    Cheers,

    Michi.
  • Thanks again

    Thanks for the protected destructor idea.