🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

3 total messages Started by Bjarne Stroustrup Mon, 15 Sep 1986 16:19
Standard C routines calling C++ (non-member) functions
#313
Author: Bjarne Stroustrup
Date: Mon, 15 Sep 1986 16:19
86 lines
3042 bytes
> From: bershad@ucbvax (Brian Bershad)
> Subject: Standard C routines calling C++ (non-member) functions
> Organization: University of California at Berkeley
>
> I am running into a strange problem when linking in C++ code with Old C.
> 
> The following code shows what is happening:

	/* THIS IS STANDARD C */
	extern void foo();

	main()
	{
  	int x = 23;
  	foo(&x,&x);
	}

> ----------------------------

	/* THIS IS C++ */
	#include <sys/types.h>
	#include <sys/stat.h>

	int lstat(char*, stat*);

	void foo(int *x, int *y)
	{
		struct stat stbuf;
		lstat("/etc/motd", &stbuf);
	
		return;
	}

> ------------------------------------
> 
> and they are compiled as:
> 	% cc -c main.c
> 	% CC -c foo.c main.o
> 

> When I write into &stbuf via the lstat, the foo's return
> address seems to get clobbered, and the program core
> dumps with an illegal instruction at the return statement,
> with the values for x and y getting set to nil.

I conjecture that you are using a SysV declaration of ``struct stat'' in
/usr/include/CC/sys/stat.h from C++ and a BSD4.? declaration ``struct stat''
in /usr/include/sys/stat.h from C. Since the BSD stat is larger than the SysV
stat you are in trouble. Please modify /usr/include/CC/sys/stat.h to fit
your system.

> More annoyingly, the following core dumps in ostream...
> 
> void foo(int* x, int* y)
> {
> 	cerr << *x;
> 	cerr << *y;
> }
> 
> when it is called from a C program (for reasons that are beyond
> me... I can guess on the first example, but on this one, I have no
> idea).

I conjecture that you did not load the program using CC so that the constructors
initializing cin, cout, and cerr were not called. A similar effect (core dump
on the first C++ stream I/O operation) can be obtained by not compiling main()
by CC.

> Since I am writing a fairly substantial package that uses
> somebody else's RPC (with stubs generated in C) routines,
> the fact that this stuff doesn't work is causing me numerous
> headaches.

Sorry about that, and thankyou for complaining where others can benefit from
your experiences. It ought to work. Please confirm or complain again.
 
> What is C++ expecting on the stack frame for non-member functions
> that old C is not putting there???

Nothing, C++ does not diddle with stack layouts or with structure layouts for
functions or structures that can be expressed in C.

>	Brian Bershad
>	University Washington Comp Sci
>	brian@uw-bluechip.arpa
>	bershad@ucbvax.berkeley.edu | ucbvax!bershad
Re: Standard C routines calling C++ (non-member) functions
#327
Author: Brian Bershad
Date: Tue, 23 Sep 1986 06:47
113 lines
4416 bytes
This is in response to BS's very helpful response on
problems involving integrating c++ with standard c.

Problem 1:


>	/* THIS IS STANDARD C */
>	extern void foo();
>
>	main()
>	{
>  	int x = 23;
>  	foo(&x,&x);
>	}
>
>> ----------------------------
>
>	/* THIS IS C++ */
>	#include <sys/types.h>
>	#include <sys/stat.h>
>
>	int lstat(char*, stat*);
>
>	void foo(int *x, int *y)
>	{
>		struct stat stbuf;
>		lstat("/etc/motd", &stbuf);
>	
>		return;
>	}
>
> ------------------------------------
> 
> and they are compiled as:
> 	% cc -c main.c
> 	% CC -c foo.c main.o
> 
>
> When I write into &stbuf via the lstat, the foo's return
> address seems to get clobbered, and the program core
> dumps with an illegal instruction at the return statement,
> with the values for x and y getting set to nil.
>

BS's response:
>>I conjecture that you are using a SysV declaration of ``struct stat'' in
>>/usr/include/CC/sys/stat.h from C++ and a BSD4.? declaration ``struct stat''
>>in /usr/include/sys/stat.h from C. Since the BSD stat is larger than the SysV
>>stat you are in trouble. Please modify /usr/include/CC/sys/stat.h to fit
>>your system.

Yes. Exactly.  I have since converted all of the 4.3 /usr/include
files to work with C++.  

> More annoyingly, the following core dumps in ostream...
> 
> void foo(int* x, int* y)
> {
> 	cerr << *x;
> 	cerr << *y;
> }
> 
> when it is called from a C program (for reasons that are beyond
> me... I can guess on the first example, but on this one, I have no
> idea).

BS's response:

>>I conjecture that you did not load the program using CC so that the constructors
>>initializing cin, cout, and cerr were not called. A similar effect (core dump
>>on the first C++ stream I/O operation) can be obtained by not compiling main()
>>by CC.

You got it.
Yes, they were loaded properly.
The problem seems to only happen when you call a C++ function from 
standard C main().  If I reverse the calling sequence, things work.
I guess, in retrospect, this makes sense.

> Since I am writing a fairly substantial package that uses
> somebody else's RPC (with stubs generated in C) routines,
> the fact that this stuff doesn't work is causing me numerous
> headaches.
>
>>Sorry about that, and thankyou for complaining where others can benefit from
>>your experiences. It ought to work. Please confirm or complain again.

No apologies needed. 
In general, integrating large amounts of C code (> 500 lines) with
large amounts of C++ code (> 5000 lines), seems to work ok.  I
have some nasty sed/awk scripts to clean up the RPC generated headers
for the stubs to make them both C and C++ compatible, and there are still some 
strange problems with passing enumerated types between C and C++,
but things are going well, and I don't think I would have
been able to handle this much code as effectively had I done
it in C.  (though I still have to convince my advisor
that doing this in C++ was a good idea...... )

I have an unrelated (possibly naive) question.  I am using dbx
to debug my code, and I was rather surprised to find that
dbx can relate C++ statements (not those in the ..c files)
to the pc, so I can smoothly trace execution from the debugger.
I have to do all the name translation by hand (ie. Class::function
becomes Class_function, prepending _auto_ to most things, etc...),
but dbx is able to map my .c source code to the executable so
I can trace through things and see the original C++ code.
Since it is really the ..c files that are being compiled with
/bin/cc, how is dbx able to do this??  This is not a complaint.


	Brian Bershad
	University of Washington Computer Science
	bershad@ucbvax.berkeley.edu || ucbvax!bershad || brian@uw-june.arpa
Re: Standard C routines calling C++ (non-member) functions
#332
Author: Joseph S. D. Yao
Date: Wed, 01 Oct 1986 14:11
24 lines
1742 bytes
In article <1221@uw-june> brian@uw-june.UUCP (Brian Bershad) writes:
>> More annoyingly, the following core dumps in ostream...
>> void foo(int* x, int* y) ...
>> when it is called from a C program (for reasons that are beyond
>BS's response:
>>>I conjecture that you did not load the program using CC so that the constructors
>>>initializing cin, cout, and cerr were not called. A similar effect (core dump
>>>on the first C++ stream I/O operation) can be obtained by not compiling main()
>>>by CC.
>You got it.
>Yes, they were loaded properly.
>The problem seems to only happen when you call a C++ function from 
>standard C main().  If I reverse the calling sequence, things work.
>I guess, in retrospect, this makes sense.

In the C++ that I installed, there is a clearly defined procedure
to make C++ run from C.  One must call a certain routine from main()
before calling any C++.  It is not in the book, so it must be in the
installation instructions (which I do not have near me).  Check
there.
-- 

	Joe Yao		hadron!jsdy@seismo.{CSS.GOV,ARPA,UUCP}
			jsdy@hadron.COM (not yet domainised)
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads