Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

CORBA Discussion :

CORBA - C++ - Probleme avec les sequences


Sujet :

CORBA

  1. #1
    Membre du Club
    CORBA - C++ - Probleme avec les sequences
    Bonjour,

    j'ai besoin dans le cadre de mon projet d'inserer a mon interface une sequence<double> (pour avoir une liste de coefficients dynamique)

    J'ai repris l'exemple de base et comme je veux eviter au maximum les new (qui entraine souvent des fuites memoires), j'ai essaye d'utiliser des references sauf qu'au 2nd appel de ma sequence, j'ai droit a Caught a CORBA::COMM_FAILURE chez le client et pour le serveur un erreur de plusieurs pages commencant par :

    Upcall Hello!
    2
    *** glibc detected *** ./Server: double free or corruption (fasttop): 0x0000000001e022d0 ***
    ======= Backtrace: =========


    Voici mon code :
    Tout d'abord Echo.idl
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    typedef sequence<double> SeqCoef;
    
    interface Echo{
      string echoString(in string mesg);
    
      attribute SeqCoef coef;
    };
    Ensuite le serveur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    #include "Echo.hh"
    #include <stdlib.h>
    
    #ifdef HAVE_STD
    # include <iostream>
    using namespace std;
    #else
    # include <iostream.h>
    #endif
    class Echo_i : public POA_Echo
    {
    public:
      inline Echo_i() {liste.length(0);}
      virtual ~Echo_i() {}
      virtual char* echoString(const char* mesg);
      virtual SeqCoef* coef();
      virtual void coef(const SeqCoef&);
    
      SeqCoef liste;
    };
    char* Echo_i::echoString(const char* mesg)
    {
      cout << "Upcall " << mesg << endl;
      cout << liste.length()<<endl;
      string tmp = std::string(mesg)+ "toto";
      return CORBA::string_dup(tmp.c_str());
    }
    
    SeqCoef* Echo_i::coef(){
      return &liste;
    }
    void Echo_i::coef(const SeqCoef& val){
      /*liste->length(val.length());
      for(int i=0 ; i<val.length();i++){
        (*liste)[i]=val[i];
        }*/
      liste = val;
    }
    //////////////////////////////////////////////////////////////////////
    int main(int argc, char** argv)
    {
      try {
        CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
        CORBA::Object_var obj = orb->resolve_initial_references("RootPOA");
        PortableServer::POA_var poa = PortableServer::POA::_narrow(obj);
        Echo_i* myecho = new Echo_i();
    
        SeqCoef test;
        test.length(2);
        test[0]=108;
        test[1]=64;
        myecho->coef(test);
        PortableServer::ObjectId_var myechoid = poa->activate_object(myecho);
        // Obtain a reference to the object, and print it out as a
        // stringified IOR.
        obj = myecho->_this();
        CORBA::String_var sior(orb->object_to_string(obj));
        cout << (char*)sior << endl;
        myecho->_remove_ref();
        PortableServer::POAManager_var pman = poa->the_POAManager();
        pman->activate();
        orb->run();
      }
      catch(CORBA::SystemException& ex) {
        cerr << "Caught 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;
    }
    Enfin le client
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    #include "Echo.hh"
    #ifdef HAVE_STD
    # include <iostream>
    # include <fstream>
    using namespace std;
    #else
    # include <iostream.h>
    #endif
    static void hello(Echo_ptr e)
    {
      CORBA::String_var src = (const char*) "Hello! ";
      CORBA::String_var dest = e->echoString(src);
      cout << "I said, \"" << (char*)src << "\"." << endl
           << "The Echo object replied, \"" << (char*)dest <<"\"." << endl;
      SeqCoef *test= e->coef();
      cout <<"test ="<<test->length()<<endl;
    
      SeqCoef *test2= e->coef();
      cout <<"test2 ="<<test2->length()<<endl;
    }
    //////////////////////////////////////////////////////////////////////
    int main(int argc, char** argv)
    {
      try {
        CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
        if( argc != 2 ) {
          cerr << "usage: eg2_clt <object reference>" << endl;
          return 1;
        }
        CORBA::Object_var obj = orb->string_to_object(argv[1]);
        Echo_var echoref = Echo::_narrow(obj);
        if( CORBA::is_nil(echoref) ) {
    
          cerr << "Can’t narrow reference to type Echo (or it was nil)." << endl;
          return 1;
        }
        for (CORBA::ULong count=0; count<10; count++)
          hello(echoref);
        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;
    }
    Est-ce que le probleme ne viendrait pas des "deep copy"?

    Merci de votre aide

  2. #2
    Membre averti
    Bonjour,

    Le problème vient de l'implémentation de l'opération coef() côté serveur.
    Par convention CORBA laisse à l'appelant (le client) la responsabilité la gestion mémoire de l'objet retourné par l'opération du serveur. Il faut donc lui renvoyer une copie de la liste.
    L'ORB du serveur va ensuite détruire l'objet retourné par l'opération coef() juste après envoi de la requête retour au client. Donc ton cas liste est détruit au 1er appel. Au 2e appel, il est par chance encore accessible en mémoire, mais en fin de requête un 2e delete est fait (d'où le "double free").

    Une implémentation correcte serait celle-ci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SeqCoef* Echo_i::coef(){
      return new SeqCoef(liste);
    }

  3. #3
    Membre du Club
    Donc je suis oblige de faire appel a new.

    Je dois donc ensuite faire dans mon client pour liberer ma memoire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    ...
    SeqCoef *test= e->coef();
    ...
    delete test;
    Merci de ton aide

  4. #4
    Membre averti
    Bonjour,

    Le mieux c'est d'utiliser un type _var côté client.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    ...
    {
        SeqCoef_var test= e->coef();
        ...
    }
    // en fin de scope l'objet SeqCoef_var est détruit 
    // et le pointeur qu'il encapsule aussi.