Discussion:
[omniORB] heap corruption in _CORBA_Sequence destructor
Andrew Buza
2008-08-26 06:16:49 UTC
Permalink
I posted a thread about problems I was having using CORBA sequences
back in June ( http://www.omniorb-support.com/pipermail/omniorb-list/2008-June/029546.html
). Following Martin's suggestion, I double-checked my allocations, use
of _var types, etc., but was unable to find anything that (to my eyes)
was wrong. Coming back to that problem now, I have a sample typical of
where I'm having difficulty. I have the following (abridged) IDL:

struct Node
{
string kind;
string key;
};

typedef sequence<Node> NodeList;

interface Hierarchy
{
Node getRootNode();
NodeList getChildren(in Node n);
};

My client attempts to get a list of all nodes with kind == "Queue" like so:

{
std::list<std::string> queues;
//... get Hierarchy object reference...
Node_var root = hierarchy->getRootNode();
visit_node(hierarchy, root, queues);
}

void visit_node(Hierarchy_ptr hierarchy, Node const & node,
list<string> &queues)
{
if(strcmp(node.kind,"Queue") == 0)
{
queues.push_back(string(node.key));
}

NodeList_var children = hierarchy->getChildren(node);
CORBA::ULong nchildren = children->length();
for(CORBA::ULong c = 0; c < nchildren; c++)
{
Node const & node = children[c];
visit_node(hierarchy, node, queues);
}
}

When this is run I'll get a message indicating heap corruption and the
IDE (MSVC8.0) will break in the _CORBA_Sequence destructor.

Is the listing above correct, or is there something I'm not
understanding about memory management in CORBA?
Martin Trappel
2008-08-26 12:15:50 UTC
Permalink
Post by Andrew Buza
I posted a thread about problems I was having using CORBA sequences
back in June ( http://www.omniorb-support.com/pipermail/omniorb-list/2008-June/029546.html
). Following Martin's suggestion, I double-checked my allocations, use
of _var types, etc., but was unable to find anything that (to my eyes)
was wrong. Coming back to that problem now, I have a sample typical of
struct Node
{
string kind;
string key;
};
typedef sequence<Node> NodeList;
interface Hierarchy
{
Node getRootNode();
NodeList getChildren(in Node n);
};
{
std::list<std::string> queues;
//... get Hierarchy object reference...
Node_var root = hierarchy->getRootNode();
visit_node(hierarchy, root, queues);
}
void visit_node(Hierarchy_ptr hierarchy, Node const & node,
list<string> &queues)
{
if(strcmp(node.kind,"Queue") == 0)
{
queues.push_back(string(node.key));
}
NodeList_var children = hierarchy->getChildren(node);
CORBA::ULong nchildren = children->length();
for(CORBA::ULong c = 0; c < nchildren; c++)
{
Node const & node = children[c];
visit_node(hierarchy, node, queues);
}
}
When this is run I'll get a message indicating heap corruption and the
IDE (MSVC8.0) will break in the _CORBA_Sequence destructor.
Is the listing above correct, or is there something I'm not
understanding about memory management in CORBA?
Your code looks OK to me.
Indeed, when I set up a very simple example with your IDL I don't have
any problems. (see attached example file)
Have you run your tests in-process or remotely?

br,
Martin
-------------- next part --------------
//
// Example code for implementing IDL interfaces in file node.idl
//
#include "stdafx.h"
#include <iostream>
#include "node.hh"
#include <boost/foreach.hpp>
#include <list>

//
// Example class implementing IDL interface Hierarchy
//
class Hierarchy_i: public POA_Hierarchy {
private:
// Make sure all instances are built on the heap by making the
// destructor non-public
//virtual ~Hierarchy_i();
public:
// standard constructor
Hierarchy_i();
virtual ~Hierarchy_i();

// methods corresponding to defined IDL attributes and operations
Node* getRootNode();
NodeList* getChildren(const Node& n);

};

//
// Example implementational code for IDL interface Hierarchy
//
Hierarchy_i::Hierarchy_i(){
// add extra constructor code here
}
Hierarchy_i::~Hierarchy_i(){
// add extra destructor code here
}
// Methods corresponding to IDL attributes and operations
Node* Hierarchy_i::getRootNode(){
// insert code here and remove the warning
Node_var n = new Node;
n->key = "ROOT";
n->kind = "X";
return n._retn();
}

NodeList* Hierarchy_i::getChildren(const Node& n){
// insert code here and remove the warning
NodeList_var nl = new NodeList;
if(0==strcmp(n.key, "ROOT")) {
nl->length(2);
nl[0].kind = "C";
nl[0].key = "Child 1";
nl[1].kind = "C";
nl[1].key = "Child 2";
}
return nl._retn();
}



// End of example implementational code

using namespace std;
void visit_node(Hierarchy_ptr hierarchy, Node const & node, list<string> &queues)
{
if(strcmp(node.kind,"C") == 0)
{
queues.push_back(string(node.key));
}

NodeList_var children = hierarchy->getChildren(node);
CORBA::ULong nchildren = children->length();
for(CORBA::ULong c = 0; c < nchildren; c++)
{
Node const & node = children[c];
visit_node(hierarchy, node, queues);
}
}

int main(int argc, char** argv)
{
using namespace std;
try {
// Initialise the ORB.
CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);

// Obtain a reference to the root POA.
CORBA::Object_var obj = orb->resolve_initial_references("RootPOA");
PortableServer::POA_var poa = PortableServer::POA::_narrow(obj);

// We allocate the objects on the heap. Since these are reference
// counted objects, they will be deleted by the POA when they are no
// longer needed.
Hierarchy_i* myHierarchy_i = new Hierarchy_i();


// Activate the objects. This tells the POA that the objects are
// ready to accept requests.
PortableServer::ObjectId_var myHierarchy_iid = poa->activate_object(myHierarchy_i);

Hierarchy_var h;

// Obtain a reference to each object and output the stringified
// IOR to stdout
{
// IDL interface: Hierarchy
CORBA::Object_var ref = myHierarchy_i->_this();
CORBA::String_var sior(orb->object_to_string(ref));
std::cout << "IDL object Hierarchy IOR = '" << (char*)sior << "'" << std::endl;
h = Hierarchy::_narrow(ref);
}

// Obtain a POAManager, and tell the POA to start accepting
// requests on its objects.
PortableServer::POAManager_var pman = poa->the_POAManager();
pman->activate();

{
std::list<std::string> queues;
Node_var root = h->getRootNode();
cout << root->key << endl;
visit_node(h, root, queues);
queues;
}

// orb->run();

orb->destroy();
}
catch(CORBA::TRANSIENT&) {
cerr << "Caught system exception TRANSIENT -- unable to contact the "
<< "server." << endl;
}
catch(CORBA::SystemException& ex) {
cerr << "Caught a CORBA::" << ex._name() << endl;
}
catch(CORBA::Exception& ex) {
cerr << "Caught CORBA::Exception: " << ex._name() << endl;
}
catch(omniORB::fatalException& fe) {
cerr << "Caught omniORB::fatalException:" << endl;
cerr << " file: " << fe.file() << endl;
cerr << " line: " << fe.line() << endl;
cerr << " mesg: " << fe.errmsg() << endl;
}
return 0;
}
Andrew Buza
2008-08-26 23:58:29 UTC
Permalink
Post by Martin Trappel
Your code looks OK to me.
Indeed, when I set up a very simple example with your IDL I don't have any
problems. (see attached example file)
Have you run your tests in-process or remotely?
br,
Martin
Thanks again Martin. Based on tests I've run here and what you wrote
above I now suspect that the problem isn't with omniORB or my code,
but with the host application that loads & runs it.

Loading...