-1

I'm having some issues with the Virtual Machine I was supposed to work with to make a C++ project, it regularly compiles both on DevC++ and CodeBlocks (Eureka!), runs and does exactly what it is meant for. Anyway, I tried to start the execution from the Terminal but it crashes giving the following message:

main.cpp:(.text.startup+0x1586): undefined reference to `move_red(vettore<vettore<blue_car> >*, vettore<vettore<red_car> >*, unsigned int, unsigned int, unsigned int*)'

(It actually gives this error with different methods, but the error issue is the same.)

From Terminal, I executed using:

chmod +x build.sh; $ g++ -O2 -std=c++11 -o output main.cpp

This is the incriminated function:

void move_red(vettore<vettore<blue_car> > * v_col, vettore< vettore< red_car> > * v_row,unsigned int M,unsigned int N,unsigned int *n){

 vettore<blue_car> * pb;
 vettore<red_car> * pr;
 for(unsigned int kk=0;kk<M;kk++){ 

              pr=&((*v_row)[kk]); 
              for(unsigned int ll=0;ll<n[kk];ll++){
                           (pr->get_obj()).set_bloc(is_bloc_r(pr,&((*v_row)[kk]),v_col));
                           pr=pr->get_next(); 
                           }
              }
 for(unsigned int kk=0;kk<M;kk++){

              pr=&((*v_row)[kk]); 
              unsigned int ll;
              for(ll=0;ll<n[kk]-1;ll++){ 
                           if ((pr->get_obj().get_bloc()==0)) pr->get_obj().move_red();
                           pr=pr->get_next();
                           }
                           if((pr->get_obj().get_j()==N-1)&&((pr->get_obj().get_bloc()==0))){ 
                                     pr->get_obj().move_red_border();
                                     ((*v_row)[kk]).order(); 
                                    }
                           else if((pr->get_obj().get_bloc()==0)){
                                pr->get_obj().move_red(); 
                                }
              }
 };


void move_blue(vettore<vettore<blue_car> > * v_col, vettore< vettore< red_car> > * v_row,unsigned int M,unsigned int N,unsigned int *m){

     vettore<blue_car> * pb;
     vettore<red_car> * pr;

     for(unsigned int ll=0;ll<N;ll++){

          pb=&((*v_col)[ll]); 
          for(unsigned int kk=0;kk<m[ll];kk++){
                   (pb->get_obj()).set_bloc(is_bloc_b(pb,&((*v_col)[ll]),v_row));
                   pb=pb->get_next();
                   }
      }

     for(unsigned int ll=0;ll<N;ll++){

          pb=&((*v_col)[ll]);
          unsigned int kk;
          for(/*unsigned int */kk=0;kk<m[ll]-1;kk++){ 
                       if ((pb->get_obj().get_bloc()==0)&&pb->get_next()!=nullptr) pb->get_obj().move_blue();
                       pb=pb->get_next();
                       }
                       if((pb->get_obj().get_i()==M-1)&&((pb->get_obj().get_bloc()==0))){                                          pb->get_obj().move_blue_border();
                                 ((*v_col)[ll]).order(); 
                                }
                       else if((pb->get_obj().get_bloc()==0)){
                            pb->get_obj().move_blue();
                            }

          }
};

If needed, this is the main:

int main(int argc, char *argv[]){
bool error=0;
ifstream file("problem.csv");
if(file.fail()) {
                error=1;

                }
unsigned int N = 0;
unsigned int M = 0;
char c; 

int i=-1,j=0, k=0, n_iter, j_temp =0;

vettore<blue_car>  vb; 
vettore<red_car>  vr;

vettore< vettore <red_car> > v_row(vr); 
vettore< vettore <blue_car> > v_col(vb);
vettore<unsigned int> iter(0); 

std::string iterazioni;
std::string iteraz;

if(!error){

                    std::getline(file,iterazioni,'\n'); 
                    stringstream it(iterazioni);       
                      while (it.good() && i==-1) {
                                       std::getline(it,iteraz, ','); 
                                       iter[k] = atoi(iteraz.c_str());
                                                  if(iter[k]<0){
                                                                 error=1;
                                                                 break;
                                                                    }

                                        iter.append(0); 
                                                  k++;

                                }
                                    iter.remove_tail();

                                    i=0;
                                    n_iter=iter.get_size();

                                    }

if(!error){

while(file.get(c) && !error)
                  {

                        if((v_row.get_size()<i+1)||(v_col.get_size()<j+1)){
                                                                        if(i==0) {j_temp=v_col.get_size();}
                                                                        while(v_row.get_size()<1+i){
                                                                                               v_row.insert_tail(vr); 
                                                                                               }
                                                                        while(v_col.get_size()<j+1){
                                                                                                    v_col.insert_tail(vb); 
                                                                                                     }
                                                                        }

                        if (c=='1'){
                                   if(v_col[j].get_size()==1 && ((v_col[j])[0]).has_sense()==0){
                                                             v_col[j][0].set_2(i,j);
                                                             }
                                   else{
                                       blue_car * add_b = new blue_car;
                                       add_b->set_2(i,j);
                                       (v_col[j]).insert_tail(*add_b); 
                                       delete add_b;
                                       }
                                   }

                        if (c=='2'){
                                    if(v_row[i].get_size()==1 && ((v_row[i])[0]).has_sense()==0){
                                                             v_row[i][0].set_2(i,j);
                                                             }
                                    else{
                                         red_car * add_r = new red_car;
                                         add_r->set_2(i,j);
                                         (v_row[i]).insert_tail(*add_r); 
                                         delete add_r;
                                         }
                                    }



                        if (c==',') j++;

                        if (c=='\n'){
                                     i++;
                                     if (j != j_temp){
                                                      error=1;
                                                     break;
                                                     }
                                     j=0;
                                     }


                        if ((c!='\n') && (c!=',') && (c!='0') && (c!='1') && (c!='2')){
                                                                                      error=1;
                                                                                     break;
                                                                                     }
                        //n_iter = k-1;
                        N=v_col.get_size();
                        M=v_row.get_size();

                       }


    file.close();

                 }


 //n_iter =iter.get_size();
 M=v_row.get_size();
 N=v_col.get_size();
 unsigned int *n= new unsigned int[M];
 unsigned int *m= new unsigned int[N];
 for(int i=0;i<M;i++) n[i]=v_row[i].get_size();
 for(int i=0;i<N;i++) m[i]=v_col[i].get_size();


 unsigned int * iter_a= new unsigned int[iter.get_size()];
 for(unsigned int y=0;y<n_iter;y++) iter_a[y]=iter[y];

 std::sort(iter_a, iter_a + n_iter);

 unsigned int temp_iniz_iter = 0; 
 unsigned int temp_fine_iter;// = iter_a[0]; 
 for(int volte = 0; volte < n_iter; volte ++) { 
    temp_fine_iter = iter_a[volte]; 
    for(int iter__ = temp_iniz_iter; iter__ < temp_fine_iter; iter__ ++) {/
            if(temp_iniz_iter % 2){
                              move_red(&v_col,&v_row,M,N,n); 
                              iter__++; 
                              if(iter__<temp_fine_iter) move_blue(&v_col,&v_row,M,N,m); 
                              }
            else{
                 move_blue(&v_col,&v_row,M,N,m); 
                 iter__++; 
                 if(iter__<temp_fine_iter) move_red(&v_col,&v_row,M,N,n); 

                 }
            }
    print_csv(temp_fine_iter, &v_row, M, &v_col, N);
    temp_iniz_iter = temp_fine_iter; 

                            }
    //print_csv(temp_fine_iter, &v_row, M, &v_col, N);


delete[] iter_a;
/*if(!error) std::cout<<"Il programma Ë terminato con successo\a"<<endl;
else std::cout<<"Il programma Ë terminato con errori"<<endl;
system("PAUSE");*/
return EXIT_SUCCESS;
}

And these are my classes:

template<class T> class vettore{
      private:
              T my_object; //container
              vettore <T> * next; //puntatore al prossimo elemento della lista
      public:
             vettore():next(nullptr){}; //default constructor
             vettore(T oggetto, vettore <T> * successivo=nullptr):next(successivo),my_object(oggetto){}; //faccio puntare la lista a quell'elemento 

             vettore(const vettore <T> &x):next(x.next),my_object(x.my_object){}; //copy constructor

             ~vettore(){//destructor
                       if(next!=nullptr){
                                         delete next;
                                         delete this;
                                         }
                       };



          vettore <T> * get_next(){
                  return next;};

          T get_my(){return my_object;};

          vettore<T> * ret_punt(unsigned int n){
                     if(n==0) return this;
                     if(n>=this->get_size()){std::cout<<"FUORI"<<std::endl;
                                                                           return this;}
                     vettore<T> * p=this;
                     for(unsigned int i=0;i<n;i++) p=p->get_next();
                     return p;
                     };

          T& get_obj(){ //ottenere l'oggetto by reference
                      return my_object;
                      };       
          vettore& operator=(vettore &x){ //overloading dell'operatore =
                  if(this!=nullptr) delete this;
                  unsigned int n;
                  n=x.get_size();

                  for(int i=0;i<n;i++){
                          (*this).insert_tail(x[i]);
                          }
                  return *this; //ritorna la cosa cui sta puntando this
                  };

          void ordina(){

               //vettore<T>*new_this=this;
               vettore<T>*aux=this;
               vettore<T>*punt_a_min=aux;
               bool sentinella=0;
               T min=aux->get_my();
               while(aux->get_next()!=nullptr){
                                               aux=aux->get_next();
                                               if(aux->get_my()<min){
                                                                   sentinella=1;  
                                                                   min=aux->get_my();
                                                                   punt_a_min=aux;
                                                                   }

                                               }
               if(sentinella==1){ 
                                 punt_a_min->set_obj(this->get_my());              
                                 this->set_obj(min);
                                 }
               if(this->get_next()!=nullptr) *(this->get_next()).ordina();                  
               };

          void set_next(vettore<T>*e){
               next=e;
               }

          void set_obj(T obj){
               my_object=obj;
               };

          void order(){
               unsigned int n=(*this).get_size();
               if(n==2){
                        T * p=new T;
                        p[0]=next->get_my();
                        next->set_obj(my_object);
                        my_object=p[0];
                        }
               if(n>2){
                   T * p=new T[n];
                   vettore<T> * aux=this;
                   for(unsigned int i=0;i<n;i++){
                                p[i]=aux->get_my();
                                aux=aux->get_next();
                                //I++
                                }
                   aux=this;
                   for(unsigned int i=0;i<n-1;i++){
                                aux=aux->get_next();
                                aux->set_obj(p[i]);
                                }
                   this->set_obj(p[n-1]);
                   delete []p;
                   }
               };

          void append(T obj){
               vettore<T> * aux=this;
               while(aux->get_next()!=nullptr) aux=aux->get_next();
               aux->set_next(new vettore <T>); //lo faccio puntare da aux->next al posto di nullptr ~ next=&v
               aux=aux->get_next();
               aux->set_obj(obj);
               aux->set_next(nullptr);
               };

          void insert_tail(T obj){
               vettore<T> * aux=this;
               while(aux->get_next()!=nullptr) aux=aux->get_next();

                    aux->set_next(new vettore <T>);
                    aux=aux->get_next();
                    aux->set_obj(obj);
                    aux->set_next(nullptr);
               };



          void remove_tail(){
               vettore<T> * aux=this;
               while(aux->get_next()->get_next()!=nullptr) aux=aux->get_next();
               delete aux->get_next();
               aux->set_next(nullptr);
               };

          unsigned int get_size(){
                   if(this==nullptr) return 0;
                   if(this->next==nullptr) return 1;
                   return 1+(*(this->next)).get_size();
                   };


          bool has_sense(){
              return 1;
              };

          T& operator[](unsigned int n){ 
                   if(this->get_size()-1<n) std::cout<<"elemento non accessibile"<<std::endl;
                   if(n==0) return my_object;
                   else{
                        vettore<T> * aux=this;
                        for(int ii=0;ii<n;ii++) aux=aux->get_next();
                        return aux->get_obj();        
                                }
                                };
          };
class car {

  protected:
            int i;
            int j;
            bool bloc;
  public:

         car():i(-1),j(-1),bloc(0){}; //default constructor
         car(int i,int j,bool bloc):i(i),j(j),bloc(bloc){}; //first constructor
         car(int i,int j):i(i),j(j),bloc(0){}; //second constructor
         car(const car & un_altro):i(un_altro.i),j(un_altro.j),bloc(un_altro.bloc){}; //copy constructor
         virtual ~car(){}; //destructor
         car &operator=(const car &x){
             i=x.i;
             j=x.j;
             bloc=x.bloc;
             return *this;
             };


         void set_i(int a){
              i=a;
              };

         void set_j(int b){
              j=b;
              };

         void set_bloc(bool c){
              bloc=c;
              };

         void set_2(int a, int b){
              i=a;
              j=b;
              };

         void set_3(int a, int b,bool c){
              i=a;
              j=b;
              bloc=c;
              };     
         int get_i(){
             return i;
             };

         int get_j(){
             return j;
             };

         bool get_bloc(){
              return bloc;
              };
         //print

         bool has_sense(){
              return(i>=0 && j>=0);
              };



         virtual void print(){
                 std::cout<<"Questa car si trova in posizione ("<<i<<","<<j<<") ed è "<<bloc<<"*bloccata"<<std::endl;
                 };
         };






class red_car:public car{


public:
    red_car():car(){};
    red_car(int i,int j, bool bloc):car(i,j,bloc){};
    red_car(int i, int j):car(i,j){};
    red_car(const red_car & un_altro):car(un_altro){}; //copy constructor ereditato

    red_car &operator=(const red_car &x){
             i=x.i;
             j=x.j;
             bloc=x.bloc;
             return *this;
             };

    void move_red(){
         if(j>=0) j++;
         bloc=0;
         };         

    bool has_sense(){
              return(i>=0 && j>=0);
              };

    void move_red_border(){
         if(j>=0) j=0;
         bloc=0;
         };          
    }; 

class blue_car:public car{


public:
    blue_car():car(){};
    blue_car(int i,int j, bool bloc):car(i,j,bloc){};
    blue_car(int i, int j):car(i,j){};
    blue_car(const blue_car & un_altro):car(un_altro){}; //copy constructor ereditato

    blue_car &operator=(const blue_car &x){
             i=x.i;
             j=x.j;
             bloc=x.bloc;
             return *this;
             };

    void move_blue(){
         if(i>=0) i++;
         bloc=0;
         };

    bool has_sense(){
              return(i>=0 && j>=0);
              };

    void move_blue_border(){
         if(i>=0) i=0;
         bloc=0;
         };                              
                 };

Can you please tell me what is going on?

Thank you for your time.

Scott Stensland
  • 26,870
  • 12
  • 93
  • 104
  • Do you get the error during compilation or during execution? Wait, actually: in what file(s) are `void move_red()` and `void move_blue()` defined - in `main.cpp` or somewhere else? – iksemyonov Feb 20 '16 at 17:34
  • @iksemyonov They are in a cpp/hpp couple of files, I include in the main the "move.hpp" file. The problem comes out when building, thank you! – Julia_Engl Feb 20 '16 at 17:43
  • OK then see my answer below. Simply including the `*.hpp` is not enough. – iksemyonov Feb 20 '16 at 17:43

1 Answers1

0

I think the error is in the command you use to build the project by hand:

$ g++ -O2 -std=c++11 -o output main.cpp

Instead, you need to issue the following command:

$ g++ -O2 -std=c++11 -o output main.cpp <where_move_red_and_blue_are_defined.cpp>

If the functions void move_red(/*...*/) and void move_blue(/*...*/) are defined in a source file other than main.cpp, the error you get, which is a linking error, is going to occur. The reason is, the compiler sees no definition of the functions, only the declaration, which is most likely located in a header. Thus, when the compiler sees a call to the function in the main() code, that works out fine - the declaration is enough (the declaration is found since you've included the *.hpp file into main.cpp), but when it comes to linking, i.e. joining the multiple .o object files together into a single executable, an error occurs since there is no indication as to where to find the object file where the functions are defined.

iksemyonov
  • 4,106
  • 1
  • 22
  • 42
  • I didn't know that, thank you so much. I thought adding the .hpp files would be enough so, really, thank you. – Julia_Engl Feb 20 '16 at 17:50
  • You welcome! When using IDE's the exact mechanics of the building process is indeed hidden, so switching to building by hand may be bit painful. It is well worth learning and understanding how the code is being built, though. – iksemyonov Feb 20 '16 at 17:52
  • Thank you again for letting me understand better, there was right a "conceptual" mistake so I'm glad it was fixed. – Julia_Engl Feb 20 '16 at 18:01
  • See: http://stackoverflow.com/questions/6264249/how-does-the-compilation-linking-process-work for an overview of the compilation process (searching around SO, you can find a lot of really good stuff) – iksemyonov Feb 20 '16 at 18:05