Page 1 of 2

C++ virtual methods

Posted: Mon Jan 14, 2008 9:07 pm
by znewsham
OK, I have been having some fun writing my own OS for some months, I started in ASM, and soon decided that it was not going to be right for me, so I changed to C++, I chose C++ over C as I like the object Oriented aproach to programming, Anyways, I have implemented things such as new, delete, and the funky __cxa__virtual() thingy, however I still cant get virtual functions to work, either nothing happens or the PC/bochs crashes.

Here is the setup:

I have 3 classes (that are involved in this)

CFile, CFAT, CFAT12 (CFAT16 and CFAT32 to follow)

CFile consists of:

Code: Select all

#include "CFAT.h"
class CFile
{
private:
CFAT * mpFAT;
public:
CFile(CString * pFileName)
{
 //this bits pseudo
 if (pFileName[0]=="A") //floppy
 {
  mpFAT = new CFAT12(pFileName,0);
 }
}
Open()
{
mpFAT->Open();
}
};
CFAT consists of:

Code: Select all

class CFAT
{
public:
CFAT(CString * pFileName, int drive)
{

}
virtual int getNextCluster(int cluster)=0;
Open()
{
 //do open file type stuff
 while (nextCluster!=last)
 {
  nextCluster=getNextCluster(nextCluster);
 }
}
};
CFAT12 consits of:

Code: Select all

#include "CFAT.h"
class CFAT12 : public CFAT
{
public
CFAT12(CString * pFileName, int drive) : CFAT (pFileName, drive)
{

}
int getNextCluster(int cluster)
{

}
};
now I have tried the file open method with all the code inside CFAT, and no CFAT12, and it works, so there is nothing wrong with that, but I need the specifics (namely getting next cluster) to be for each of the FAT types, and as I say it either crashes, or does nothing, I have tried a simpler example, just with a CShape and a CSquare, and it crashes.

Any Ideas?

Thanks

Zack.

Posted: Tue Jan 15, 2008 2:47 am
by AJ
Hi,

How does it crash? Are you absolutely convinced that your 'new' operator works nicely - it's not a case of allocating memory twice, or something like that? When Bochs crashes, are E/RSP and E/RIP where your would expect them to be? Is there a page fault value in CR2? Have you filled the variable 'last' correctly (is nextCluster!=last always evaluating true?).

Sorry to answer your question with questions, but I can't immediately see anything wrong with your use of the virtual function and this works OK in my OS without any support code (I don't even have __cxa__virtual() - I think this is only needed when the compiler can't find the actual function).

Oh - I've just seen, why do you set the virtual function to zero? This isn't something I've seen before (that's not to say it isn't perfectly valid...sorry for the double negative!).

Cheers,
Adam

Posted: Tue Jan 15, 2008 2:52 am
by B.E
AJ wrote:Why do you set the virtual function to zero?
This is similar to abstract in java. The function doesn't need a proper definition, also you can't instantiate the class and you must declare it in subclasses.

Posted: Tue Jan 15, 2008 2:52 am
by JamesM
Try making the function not pure virtual - i.e. removing the =0 and adding a stub {...}. See if that works. If it does, you're accessing the pure virtual function and your _cxa__virtual function is ballsed up.

Posted: Tue Jan 15, 2008 12:33 pm
by znewsham
I have tried using a non pure virtual method

I even tried using a really simple example, 2 classes, one CShapes, one CSquare, and doing a similar method, the code works in windows, but does not work when I try to use it,

I dont know what a page fault looks like, but I do not use paging, I use a flat memory model.

The new operator definatly works, as I use it for lots of other stuff as well.

When it crashes, bochs simply restarts, I am not sure what CS or IP should be, so I cant really check that.

Posted: Wed Jan 16, 2008 2:47 am
by Solar
znewsham wrote:When it crashes, bochs simply restarts, I am not sure what CS or IP should be, so I cant really check that.
Perhaps this would be a good point to implement a proper fault handling in your OS, one that prints some sort of register dump?

Posted: Wed Jan 16, 2008 3:02 am
by JamesM
I suggest mapping "INT 0x3" (debug interrupt) to print out a register dump and halt.

Posted: Wed Jan 16, 2008 5:19 am
by Cemre
you have to implement the "type_info" ( googling will help ) class with a virtual destructor "std::type_info::~type_info()"

and you have to derive "__class_type_info" "__fundamental_type_info" ( and several other [again :) google] ) classes from this "std::type_info" class, otherwise virtual functions wont work, that is, to emit the virtual tables, gcc needs those "__class_type_info" classes. and gcc emits the virtual tables only on the object file where the ( virtual ) destructor of the class is implemented. that is also why it would be a good idea to implement a virtual destructor for every class that has virtual methods. otherwise gcc complains a lot.

if those classes are not found, virtual tables will not be emitted or will be emitted with null virtual function pointers, and that will eventually lead to a crash.

Posted: Wed Jan 16, 2008 5:22 am
by JamesM
Cemre wrote:you have to implement the "type_info" ( googling will help ) class with a virtual destructor "std::type_info::~type_info()"

and you have to derive "__class_type_info" "__fundamental_type_info" ( and several other [again :) google] ) classes from this "std::type_info" class, otherwise virtual functions wont work, that is, to emit the virtual tables, gcc needs those "__class_type_info" classes. and gcc emits the virtual tables only on the object file where the ( virtual ) destructor of the class is implemented. that is also why it would be a good idea to implement a virtual destructor for every class that has virtual methods. otherwise gcc complains a lot.
Not true. My kernel uses virtual functions and doesn't require those classes.

Posted: Wed Jan 16, 2008 5:27 am
by Cemre
JamesM wrote: Not true. My kernel uses virtual functions and doesn't require those classes.
may be a difference in gcc versions,
my kernel doesn't link without those classes.

Posted: Wed Jan 16, 2008 5:27 am
by AJ
Same here - no problems with virtual functions in my OS.

@Cemre: Are those classes perhaps to do with RTTI support? (just a guess - I haven't got this in my OS yet).

Cheers,
Adam

Posted: Wed Jan 16, 2008 5:34 am
by Cemre
AJ wrote: @Cemre: Are those classes perhaps to do with RTTI support?
exactly, gcc puts the pointer of "run time type information object" of the that class to its virtual table. ( an object of class __class_type_info )

even if I disable rtti with "-fno-rtti", in my gcc version, i continue to get links related to constructor and destructor of those classes

"__class_type_info::__class_type_info()" "__class_type_info::~__class_type_info()"

Posted: Wed Jan 16, 2008 5:36 am
by JamesM
I don't. -fno-rtti disables everything for me. Perhaps you need to disable exceptions as well?

Posted: Wed Jan 16, 2008 7:17 am
by znewsham
I suggest mapping "INT 0x3" (debug interrupt) to print out a register dump and halt.
I will get on that now, is there anything in particular that I should be looking for?

Posted: Wed Jan 16, 2008 7:30 am
by JamesM
Call it when you want to check the values of registers. It's very useful.