problem in linking object files (c++/HP-UX)

  • Follow


Hi,

I have a query regarding linking from object code. First pls go 
through this
message. At the end of this I have the query.

I created the following 5 files in my home
directory; which are:- 
header1.h,header1.cpp,header2.h,header2.cpp,main.h


------------------------
// header1.h
#include "header1.cpp"
class employee;
// header1.h ends
------------------------
// header2.h
#include "header2.cpp"
class company;
// header2.h ends
------------------------
// header1.cpp
#include <stdio.h>

class employee
{
    char name[30];
	float salary;
public:
	employee() {};
    ~employee() {};
	void display() { printf("\nthis is an employeeA\n"); }
};
// header1.cpp ends
------------------------
// header2.cpp
#include <stdio.h>

class company
{
    char company_name[30];
	int total_employees;
public:
	company(){};
    ~company(){};
	void display() { printf("\nthis is a companyA\n"); }
};
// header2.cpp ends
------------------------
// main.cpp

#include "header1.h"
#include "header2.h"

int main()
{
	employee a,b,c;
	company c1,c2,c3;
	a.display();
	c1.display();
	return 1;
}
// main ends
------------------------


Then I did the following things.

I deleted demo.out. I generated object code for main.cpp,header1.cpp 
and
header2.cpp using the following commands:-

aCC -c main.cpp header1.cpp header2.cpp

So at this stage I have main.o,header1.o and header2.o

So when I link these 3 object files it works fine and I get the 
executable
with expected behaviour:-

aCC -o demo1.out main.o header1.o header2.o

This executable(demo1.out) prints the following:-

this is an employeeA

this is companyA

Then I deleted main.cpp. Then I changed the code of header1.cpp little 
bit.
I just changed the printf statement, Not it should print "This is an 
employeeB"
(instead of "This is an employeeA" ). Now since I have only changed 
header1.cpp
I just recreated its object code using the following command:-

aCC -c header1.cpp

So at this stage we have the following object code (.o) files.

main.o (old)
header1.o (updated)
header2.o (old)

So then I tried to make new executables out of these 3 object files:-

aCC -o demo2.out main.o header1.o header2.o

So I have demo2.out now. NOW THIS IS THE QUESTION. Now since I have 
created
the executable using the updated version of header1.o ; the executable
should print "This is an employeeB". But it still prints "This is an 
employeeA".

So the output of demo2.out is the same as that of demo1.out. Why does 
it happen?

I performed this small exercise to understand linking purely from 
object code.

Thanks,
The Learner

0
Reply dhiraj.nilange (2) 1/29/2007 1:25:57 PM

learner <dhiraj.nilange@iflexsolutions.com> wrote:
> I have a query regarding linking from object code. First pls go
> through this message. At the end of this I have the query.

While there are no doubt a number of folks familiar with HP aCC
lurking in this group, you may want to try asking in comp.sys.hp.hpux
too.

When you do, be certain to include the rev of the HP-UX OS you are
running, as well as the rev of the aCC you are using, and any aCC
patches you may have installed on the system.  Things like that are
almost always requested by folks when trying to work-out what might be
happening.

sincerely,

rick jones
-- 
oxymoron n, commuter in a gas-guzzling luxury SUV with an American flag
these opinions are mine, all mine; HP might not want them anyway... :)
feel free to post, OR email to rick.jones2 in hp.com but NOT BOTH...
0
Reply rick.jones2 (1065) 1/30/2007 1:41:32 AM


"learner" <dhiraj.nilange@iflexsolutions.com> writes:

> ------------------------
> // header1.h
> #include "header1.cpp"
> class employee;
> // header1.h ends
> ------------------------
> // header2.h
> #include "header2.cpp"
> class company;
> // header2.h ends
> ------------------------
> // main.cpp
>
> #include "header1.h"
> #include "header2.h"
>
> int main()
> {
> 	employee a,b,c;
> 	company c1,c2,c3;
> 	a.display();
> 	c1.display();
> 	return 1;
> }
> // main ends
> ------------------------

The code for employee::display() has now been inlined into main.o:

  /usr/ccs/bin/nm -px main.o | grep display
  # nothing.

> Then I deleted main.cpp. Then I changed the code of header1.cpp little 
> bit. I just changed the printf statement, Not it should print "This is an 
> employeeB" (instead of "This is an employeeA" ). Now since I have only changed 
> header1.cpp I just recreated its object code using the following command:-
>
> aCC -c header1.cpp

There is no code in header1.o *at all*. So this command did nothing.

> So then I tried to make new executables out of these 3 object files:-
> aCC -o demo2.out main.o header1.o header2.o
>
> So I have demo2.out now. NOW THIS IS THE QUESTION. Now since I have 
> created the executable using the updated version of header1.o ; the executable
> should print "This is an employeeB". But it still prints "This is an 
> employeeA".

As it should, due to inlining.

If you want to prevent inlining, put class declaration into header1.h:

class employee
{
    char name[30];
    float salary;
public:
    employee();
    ~employee()
    void display();
};

and put member definitions into header1.cpp:

#include <stdio.h>
#include "header1.h"

employee::employee() { }
employee::~employee() { }
employee::display() { printf("whatever\n"); }

Now it will work the way you expect it to work.

Cheers,
-- 
In order to understand recursion you must first understand recursion.
Remove /-nsp/ for email.
0
Reply ppluzhnikov-nsp (516) 1/30/2007 3:48:18 AM

On Jan 30, 8:48 am, Paul Pluzhnikov <ppluzhnikov-...@charter.net> 
wrote:
> "learner" <dhiraj.nila...@iflexsolutions.com> writes:
> > ------------------------
> > // header1.h
> > #include "header1.cpp"
> > class employee;
> > // header1.h ends
> > ------------------------
> > // header2.h
> > #include "header2.cpp"
> > class company;
> > // header2.h ends
> > ------------------------
> > // main.cpp
>
> > #include "header1.h"
> > #include "header2.h"
>
> > int main()
> > {
> >    employee a,b,c;
> >    company c1,c2,c3;
> >    a.display();
> >    c1.display();
> >    return 1;
> > }
> > // main ends
> > ------------------------
>
> The code for employee::display() has now been inlined into main.o:
>
>   /usr/ccs/bin/nm -px main.o | grep display
>   # nothing.
>
> > Then I deleted main.cpp. Then I changed the code of header1.cpp little
> > bit. I just changed the printf statement, Not it should print "This is an
> > employeeB" (instead of "This is an employeeA" ). Now since I have only changed
> > header1.cpp I just recreated its object code using the following command:-
>
> > aCC -c header1.cpp
>
> There is no code in header1.o *at all*. So this command did nothing.
>
> > So then I tried to make new executables out of these 3 object files:-
> > aCC -o demo2.out main.o header1.o header2.o
>
> > So I have demo2.out now. NOW THIS IS THE QUESTION. Now since I have
> > created the executable using the updated version of header1.o ; the executable
> > should print "This is an employeeB". But it still prints "This is an
> > employeeA".
>
> As it should, due to inlining.
>
> If you want to prevent inlining, put class declaration into header1.h:
>
> class employee
> {
>     char name[30];
>     float salary;
> public:
>     employee();
>     ~employee()
>     void display();
>
> };
>
> and put member definitions into header1.cpp:
>
> #include <stdio.h>
> #include "header1.h"
>
> employee::employee() { }
> employee::~employee() { }
> employee::display() { printf("whatever\n"); }
>
> Now it will work the way you expect it to work.
>
> Cheers,
> --
> In order to understand recursion you must first understand recursion.
> Remove /-nsp/ for email.- Hide quoted text -
>
> - Show quoted text -

Hi Paul ,

Thanks for that. I tried that way. I have moved declarations to 
header( .h) files and definition in source (.cpp) files. It looks as 
shown below.

--------------------header1.h-----------------
class employee
{
    char name[30];
	float salary;
public:
	employee(){};
    ~employee(){};
	void display();
};
-----------------header1.cpp---------------------
#include <stdio.h>
#include "header1.h"

employee::employee(){}
employee:;~employee(){}
void employee::display() { printf("\nthis is an employeeA\n"); }
------------------header2.h------------------------------
class company
{
    char company_name[30];
	int total_employees;
public:
	company(){};
    ~company(){};
	void display();
};
--------------------------header2.cpp---------------------
#include "header2.h"
#include <stdio.h>

company::company() {}
company::~company() {}
void company::display() { printf("\nThis is a companyA\n"); }
-----------------------------
main.cpp-----------------------------------
#include "header1.h"
#include "header2.h"
int main()
{
	employee a,b,c;
	company c1,c2,c3;
	a.display();
	c1.display();
	return 1;
}
-----------------------------------------------------------------------
----

BUT now when I try to comile it I get the following error:-


$ aCC -c main.cpp header1.h header2.h

"header2.cpp", line 3: catastrophic error #2003: #include file 
"header2.h"
          includes itself
  #include "header2.h"
                      ^

1 catastrophic error detected in the compilation of "main.cpp".
Compilation terminated.

I tried a doing it with header1.cpp and header2.cpp also just to 
test ; but for that also I get error:-

$ aCC -c main.cpp header1.cpp header2.cpp
main.cpp:
"header2.cpp", line 3: catastrophic error #2003: #include file 
"header2.h"
          includes itself
  #include "header2.h"
                      ^

1 catastrophic error detected in the compilation of "main.cpp".
Compilation terminated.
header1.cpp:
"header1.cpp", line 6: error #2302: function "employee::employee()" 
has
          already been defined
  employee::employee(){}
            ^

"header1.cpp", line 7: error #2040: expected an identifier
  employee:;~employee(){}
          ^

"header1.cpp", line 7: error #2169: expected a declaration
  employee:;~employee(){}
            ^

At end of source: warning #2012-D: parsing restarts here after 
previous syntax
          error

3 errors detected in the compilation of "header1.cpp".
header2.cpp:
"header2.h", line 3: catastrophic error #2003: #include file 
"header2.cpp"
          includes itself
  #include "header2.cpp"
                        ^

1 catastrophic error detected in the compilation of "header2.cpp".
Compilation terminated.



How should I go about it??

Thanks
-L

0
Reply dhiraj.nilange (2) 1/30/2007 6:09:13 AM

"learner" <dhiraj.nilange@iflexsolutions.com> writes:

> On Jan 30, 8:48 am, Paul Pluzhnikov <ppluzhnikov-...@charter.net> 

Please learn to trim your replies.

> class employee
> {
>     char name[30];
> 	float salary;
> public:
> 	employee(){};
>     ~employee(){};
> 	void display();
> };
> -----------------header1.cpp---------------------
> #include <stdio.h>
> #include "header1.h"
>
> employee::employee(){}
> employee:;~employee(){}
> void employee::display() { printf("\nthis is an employeeA\n"); }

This is invalid code -- you provided two definitions of 
employee::employee(), and there is *no way* this code:

  employee:;~employee(){}

will compile.

Don't "transcribe" what you did, cut/paste it instead.

> BUT now when I try to comile it I get the following error:-
>
> $ aCC -c main.cpp header1.h header2.h

Compiling *.h files is a bad idea.
Compile *.cpp files instead.

> "header2.cpp", line 3: catastrophic error #2003: #include file 
> "header2.h"
>           includes itself
>   #include "header2.h"

It's obvious that the code you've tried to compile doesn't match
your description above.

According to the compiler, your header2.h (line) still contains
"#include "header2.h"'. You can't do that (for obvious reason).

> How should I go about it??

Engage brain?

Cheers,
-- 
In order to understand recursion you must first understand recursion.
Remove /-nsp/ for email.
0
Reply ppluzhnikov-nsp (516) 1/31/2007 3:35:06 AM


On Mon, 29 Jan 2007, learner wrote:

>
> Hi,
>
> I have a query regarding linking from object code. First pls go
> through this
> message. At the end of this I have the query.
>
> I created the following 5 files in my home
> directory; which are:-
> header1.h,header1.cpp,header2.h,header2.cpp,main.h
                                               ^^^^^^
You probably meant main.cpp-------------------+

> So the output of demo2.out is the same as that of demo1.out. Why does
> it happen?

There are several prolems with your code. Let me explain them to you 
step by step. If you passed the following command line to your linker:

aCC -o demo3.out main.o

(i.e. you do not pass the header1.o or header2.o files to it)

you would have noticed that your program linked successfully, without any 
complaining on undefined symbols. This happens because you are not 
actually performing separate compilation of object files and linking the 
object files together; instead you are including (albeit indirectly) the 
file header1.cpp and header2.cpp into main.cpp. Therefore main.o will 
contain the compiled code of employee::display() and company::display(). 
So the linker does not need to use header1.o and header2.o at all. Both 
these files contain another version of employee::display(), respectively 
company::display(), but the linker will not look at them to resolve 
symbols, because like I said, main.o already includes the definition of 
those functions.

There is also a more subtle point here: since you wrote 
the body of the member function (display) inside the class definition 
(Employee, and Company), C++ will imply that the function is defined as 
inline, which in C++ means that it has static linkage. Therefore the 
linker will not complain about multiply defined symbols (both in main.o 
and header1.o, respectively header2.o)

The way you wrote your code (i.e. #including .cpp files) is very bad 
programming practice, you must consult a good C++ book for how to do this 
correctly.

Here is a modified version of your code, which should work how you expect 
it. I have also renamed the files to be slightly more meaningful:

//employee.h

#ifndef EMPLOYEE_H
#define EMPLOYEE_H

class employee {
public:
 	employee(void);
 	~employee(void);
 	void display(void);
private:
 	char name[30];
 	float salary;
};

#endif /* EMPLOYEE_H */

//-------End of employee.h




//company.h

#ifndef COMPANY_H
#define COMPANY_H

class company {
public:
 	company(void);
 	~company(void);
 	void display(void);
private:
 	char company_name[30];
 	int number_of_employees;
};

#endif /* COMPANY_H */

//-----End of company.h


//employee.cpp

#include <stdio.h>
#include <string.h>

employee::employee(void)
:salary(0.0f)
{
 	strcpy(name,"");
}

employee::~employee() {}

void employee::display(void)
{
 	printf("This is Employee A\n");
}

//---End of employee.cpp


//company.cpp

#include <stdio.h>
#include <string.h>

company::company(void)
: number_of_employees(0)
{
 	strcpy(company_name,"");
}

company::~company(void)
{
}

void company::display(void)
{
 	printf("This is Company A\n");
}

//---End of company.cpp

main.cpp remains unchanged except for replacing "header1.[h,cpp,o]" and 
"header2.[h,cpp,o]" with "employee.[h,cpp,p]" respectively 
"company.[h,cpp,o]"

If you have more questions, feel free to ask, but I think that your 
problem is related to C++ and has little to do with UNIX if at all. Such 
questions are better asked in a C++ specific newsgroup.

 							Emil


>
> I performed this small exercise to understand linking purely from
> object code.
>
> Thanks,
> The Learner
>
>
0
Reply emild2 (25) 2/2/2007 3:42:42 PM

5 Replies
38 Views

(page loaded in 0.144 seconds)


Reply: