Tricky C++ question

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
DarylD

Tricky C++ question

Post by DarylD »

Okay, a question for those of you who know.

I am writing my API library in C++ (works well so far), but one thing I am stuck on is this:

I have a class called console with a constructor. I have my own created c++ new operator defined as follows:

void *operator new ( size_t nBytes ) which will call my kernel malloc function (I don't have a problem with this).
Looking at the disassembly all seems fine, but it won't call the constructor for my class when it does the new and I am not sure why, I thought this was a built-in C++ thing.

Can anyone help?
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Tricky C++ question

Post by Pype.Clicker »

i think whyme_t is the guy you need...
_mark()

Re:Tricky C++ question

Post by _mark() »

You should create a "placement new"

void *operator new( size_t, void * )

the new you created does not have a "this" pointer - thus it cannot call the constructor.

Mark
_mark()

Re:Tricky C++ question

Post by _mark() »

Sorry - I'm not sure what I was thinking. Ignor anything I say before 9am. :)

This is a built in C++ thing, the "new" operator (not operator new) should compile down to two calls. You said this looks fine when disassembled? You should see something like:

call operator new ( some_size )
; a few other things....
call console::console ( add_of_this )

If you see this, then your constructor may be defined
incorrect and the compiler is calling a "default" constructor that it is creating for you.

Mark
DarylD

Re:Tricky C++ question

Post by DarylD »

I don't get the console::console part. I get the part which calls malloc (well, my placeholder anyway) it just never seems to go on to call the constructor.

Sure its something obvious but I admit I am not a C++ guru by any stretch.
_mark

Re:Tricky C++ question

Post by _mark »

Can you post the code? At least the class declaration.
_mark

Re:Tricky C++ question

Post by _mark »

The following code:

Code: Select all

#include <stdio.h>
#include <malloc.h>


class foo1
{
public:
   int ggg;

   void *operator new( size_t s )
   {
      return( malloc( s ) );
   }

   foo1()
   {
      printf("foo1() called\n");
   }
};

main()
{
   foo1 *f = new foo1;
   return 1;
}
compiles to:

Code: Select all

>> 21:   main()
>> 22:   {
00401030   push        ebp
00401031   mov         ebp,esp
00401033   push        0FFh
00401035   push        offset __ehhandler$_main (0041327b)
0040103A   mov         eax,fs:[00000000]
00401040   push        eax
00401041   mov         dword ptr fs:[0],esp
00401048   sub         esp,50h
0040104B   push        ebx
0040104C   push        esi
0040104D   push        edi
0040104E   lea         edi,[ebp-5Ch]
00401051   mov         ecx,14h
00401056   mov         eax,0CCCCCCCCh
0040105B   rep stos    dword ptr [edi]

>> 23:       foo1 *f = new foo1;     // NOTE: call to foo1::new
0040105D   push        4
0040105F   call        @ILT+10(foo1::operator new) (0040100f)
00401064   add         esp,4
00401067   mov         dword ptr [ebp-18h],eax
0040106A   mov         dword ptr [ebp-4],0
00401071   cmp         dword ptr [ebp-18h],0
00401075   je          main+54h (00401084)
00401077   mov         ecx,dword ptr [ebp-18h]

>>                                                 // NOTE: call to foo1::foo1

0040107A   call        @ILT+0(foo1::foo1) (00401005)
0040107F   mov         dword ptr [ebp-1Ch],eax
00401082   jmp         main+5Bh (0040108b)
00401084   mov         dword ptr [ebp-1Ch],0
0040108B   mov         eax,dword ptr [ebp-1Ch]
0040108E   mov         dword ptr [ebp-14h],eax
00401091   mov         dword ptr [ebp-4],0FFFFFFFFh
00401098   mov         ecx,dword ptr [ebp-14h]
0040109B   mov         dword ptr [ebp-10h],ecx

>> 24:       return 1;
0040109E   mov         eax,1

>> 25:   }
If both new and the constructor were defined incorrect - you would see:

Code: Select all

>> 21:   main()
>> 22:   {

00401030   push        ebp
00401031   mov         ebp,esp
00401033   sub         esp,48h
00401036   push        ebx
00401037   push        esi
00401038   push        edi
00401039   lea         edi,[ebp-48h]
0040103C   mov         ecx,12h
00401041   mov         eax,0CCCCCCCCh
00401046   rep stos    dword ptr [edi]

23:       foo1 *f = new foo1; // NOTE: call to global new
00401048   push        4
0040104A   call        operator new (004010c0)
0040104F   add         esp,4
00401052   mov         dword ptr [ebp-8],eax
00401055   mov         eax,dword ptr [ebp-8]
00401058   mov         dword ptr [ebp-4],eax

24:       return 1;
0040105B   mov         eax,1

NOTE: no constructor called:

25:   }
It is probably something small your overlooking - post the code and we might be able to help more.

Mark
DarylD

Re:Tricky C++ question

Post by DarylD »

Cheers, sorted it now.

Jut got my ongoing problem with bloody PLT's in ELF, but don't worry I won't be asking for help with that, I will just wait until my brain implodes.

Daryl.
DarylD

Re:Tricky C++ question

Post by DarylD »

No, I haven't got the problem sorted :(

Remember, I have *NO* built in C++ functionality apart from the basic stuff as I have no libraries I can use, I need to create my own.

Basically what I need is a definition for new...

If i use a os::var a= new os::var(); inside a function it compiles correctly, but if I try and do it globally by defining it outside a function, the initialisation code is generated by g++ but it isn't actually called.

I.e. I have this big block of code in the disassembly but it is never called from anywhere...why??

Daryl.
_mark

Re:Tricky C++ question

Post by _mark »

Ah - I see...

Depending on the compiler, there is a function called before main() and one called after main(). The call after main is usually called atexit() - it is responsible for calling the destructors of all globally instanciated objects. The routine you are looking for is very compiler dependant, but basically you can easily find it by creating a simple C++ app with a global object. Set a break point in the constructor and look at the call stack. In any case, this is the piece of the puzzle you are probably missing. The initialization code needs to call all global constructors BEFORE main() is entered. This is not to be confused with what
new(size) or new(size,void*) do. A global object exists in the stack - not the heap. And since it was placed in the stack prior to main(), something needs to go back and call the constructor. When writting an OS, you probably bypass all the normal CRT stuff, so you will have to provide this yourself.

I suggest you look at the source for the CRT and related libraries that came with your compiler for more details on how they did it.

This is not the last obsticle you will come accross using C++.

Good Luck.
Mark
whyme_t

Re:Tricky C++ question

Post by whyme_t »

Not that I want to p1mp myself, but I've explained some of this in http://www.invalidsoftware.net/os/.
_mark

Re:Tricky C++ question

Post by _mark »

Looks like a descent totorial. How have you found writting an OS in C++ - I would think the cons far outway the pros??? What is your real experience?

Mark
whyme_t

Re:Tricky C++ question

Post by whyme_t »

The ever changing C++ Standard, and the non Standard implementation of different Compilers is Sickening. I used to enjoy C++, but the more I learn the internals and low level implementations, I see it being a bit of a 'pain in the @Ss'.

If you just want basic C++ in your OS, there is no problem. By using the support code on my site, and linking with the C++ support lib (libsupcxx.a in DJGPP), you can use global/static objects, and inheritance with no problems, as long as you disable RTTI and EH. It's only when you want polymorphism and some of the more advanced aspects of C++ that life becomes difficult.

All in all, I've had no problems interfacing asm and C++, writing ISR's, keyboard Drivers, low level memory management, etc, in C++ and ASM (I have even written member functions in pure asm) where necessary. If you want all the bells and whistles of C++, the bottom line is much much more frame work is needed. If you get it working, more power to you :) If you just want to write an OS and focus on that, don't use C++. At least until somebody sometime standardises C++, and provides support of freestanding RTLs.

P. S. This has all lead to pskyboy and I creating a new Object Oriented language. I won't reveal any details now, but keep an eye out for future news.
DarylD

Re:Tricky C++ question

Post by DarylD »

Thanks for all the help:

Whyme_t, does it matter that I am not using C++ for my kernel, only for the API library, will this have an impact on what you are suggesting?

Daryl.

PS. The tutorial is very useful.
_mark

Re:Tricky C++ question

Post by _mark »

Yes - there is quite a bit of good info in the tutorial. Thanks for sharing it.

pskyboy mentioned the language in another post. I would be interested in seeing what you all have done since I have been thinking along those same lines.

Thanks
Mark
Post Reply