2017-02-02 5 views
1

ライブラリなしでソフトウェア(カーネル)のC++コーディングを開発中です。私は新しいオペレータとdeleteオペレータについて混乱しています。私はKMalloc()とKFree()を実装しました。さて、私は、次のコーディングが標準C++ライブラリなしで動作するかどうかを知りたいと思います。コンパイラまたは標準C++ライブラリ - 新規および削除

void *mem = KMalloc(sizeof(__type__)); 
Object *obj = new (mem)(); 

、これは動作しません場合は、どのように私のセットアップどんなオブジェクト構造の任意STDのLibずに事前に割り当てられた空間でありvtableをか。

+4

これはプレースメントnewと呼ばれ、組み込み言語機能です。 –

+1

あなたはどのカーネルを考えていますか?独自の、またはLinuxカーネル。 –

+1

それは動作します。しかし、グローバル演算子 'new'と' delete'をオーバーロードして、あなたの人生をより楽にすることもできます。 – rustyx

答えて

1

その他の回答に加えて、operator newoperator deleteをオーバーロードして、 KMalloc()とプレースメントnewのトリックを行う必要があります。

// In the global namespace. 

void* operator new 
(
    size_t size 
) 
{ 
    /* You might also check for `KMalloc()`'s return value and throw 
    * an exception like the standard `operator new`. This, however, 
    * requires kernel-mode exception support, which is not that easy 
    * to get up and running. 
    */ 
    return KMalloc(size); 
} 


void* operator new[] 
(
    size_t size 
) 
{ 
    return KMalloc(size); 
} 


void operator delete 
(
    void* what 
) 
{ 
    KFree(what); 
} 


void operator delete[] 
(
    void* what 
) 
{ 
    KFree(what); 
} 

すると、次のようなコードはどうなる配置newなどの必要なすべてのコンストラクタと一緒に、必要なときにあなたのKMalloc()KFree()ルーチンを呼び出すことで動作します。

template<typename Type> 
class dumb_smart_pointer 
{ 
    public: 
     dumb_smart_pointer() 
     : pointer(nullptr) 
     {} 


     explicit dumb_smart_pointer 
     (
      Type* pointer 
     ) 
     : pointer(pointer) 
     {} 


     ~dumb_smart_pointer() 
     { 
      if(this->pointer != nullptr) 
      { 
       delete this->pointer; 
      } 
     } 


     Type& operator*() 
     { 
      return *this->pointer; 
     } 


     Type* operator->() 
     { 
      return this->pointer; 
     } 


    private: 
     Type* pointer; 
}; 


dumb_smart_pointer<int> my_pointer = new int(123); 
*my_pointer += 42; 
KConsoleOutput << *my_pointer << '\n'; 
3

まず、対象とするC++標準を定義する必要があります。私はそれが少なくともC + + 11だと思います。

一部のオペレーティングシステムカーネルでC++でコードを作成する場合は、関連するABIの仕様を慎重に検討してください(詳細はC++コンパイラのバージョンにも依存します)。例外処理やスタック巻き戻しロット)。

LinuxカーネルABIはC++に優しくないことに注意してください(x86-64ではLinuxユーザーランドABIと同じではありません)。したがって、LinuxカーネルのC++でのコーディングは妥当ではありません。

おそらく

void *mem = KMalloc(sizeof(Object)); 
Object *obj = new (mem) Object(); 

をしたい2番目のステートメントは、配置として渡された(「初期化されない」多かれ少なかれ)メモリ領域上でコンストラクタを実行するC++のplacement new機能を使用しています。

memcpyで-egオブジェクト++ Cのビット単位のコピーを気づく - ()POD Sを除いて一般的には未定義の動作であり、あなたはコンストラクタと代入演算子を使用する必要があります)

ない「配置が削除ありません"明示的にデストラクタを実行することができます:obj->~Object()objポインタで指されているオブジェクトの使用はundefined behaviorです。

ここで、そのコードが標準C++ライブラリなしで動作するかどうかを知りたいと思います。

あなたが信じているよりもはるかに難しいかもしれません。コンパイラが対象とするABIの詳細をすべて理解する必要がありますが、それは難しいことです。 を実行している

通知が適切に十分に良いorder- -inconstructors(およびdestructors)は、C++のための最も重要です。実質的に言えば、(暗黙的に)vtableフィールドを初期化していますが、オブジェクトがクラッシュすることはありません(virtualメンバー関数またはデストラクタが呼び出されるとすぐに)。

rule of five(C++ 11の場合)についても読んでください。

C++で独自のカーネルをコーディングするには、実際にはC++実装(とABI)に関する多くの詳細を理解する必要があります。

NB:事実上のスマートポインタのmemcpyで、ビット単位のコピーを言えば、std::stream -sの、std::mutex -esの、std::thread -sの - そしておそらく標準コンテナのとstd::string -sなどの... - 非常に災害を起こす可能性が高い。このような悪いことを敢行する場合は、具体的な実装の詳細を調べる必要があります。

+0

自分のカーネルをコーディングしています。 –

+0

次に、C++コンパイラのABIのすべての細部の詳細を理解するために何週間もの努力をする必要があります。 –

+1

AFAIK、Linuxカーネルの下でC++コードを実行する方法はあまりありません。しかし、これはあなたがあいまいなGCCオプション、リンカスクリプトマジック、最初の試行ではランダムなカーネルのoopses /パニックを扱わなければならないことを意味し、RTTI /例外サポートはno-noです。グローバルコンストラクタ/デストラクタでも私を始められないでください。 – 3442

関連する問題