编译器或标准C ++库 - 新增和删除

时间:2017-02-02 13:52:21

标签: c++ kernel

我正在为没有任何库的软件(内核)开发C ++编码。我对新运算符和删除运算符感到困惑。我已经实现了KMalloc()和KFree()。现在,我想知道以下编码是否可以在没有任何标准C ++库的情况下工作。

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

如果这不起作用,那么我将如何在没有任何Std Lib的预分配空间中设置vtable或任何对象结构。

2 个答案:

答案 0 :(得分:3)

首先应该定义您要定位的C ++标准。我想这至少是C ++ 11。

然后,如果您使用C ++编写某些操作系统内核代码,请注意并仔细研究相关的ABI规范(详细信息甚至取决于C ++编译器的版本,以及甚至异常处理和堆栈等血腥细节)放松很多事情)。

请注意,Linux内核ABI不是C ++友好的(它与x86-64的Linux用户登陆ABI不同)。因此,用C ++编写Linux内核编码是不合理的。

你可能想要

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

第二个语句使用C ++的placement new功能,该功能将在(作为放置位置)传递的(或多或少“unitialized”)内存区域上运行构造函数。

(注意C ++对象的按位副本-eg与memcpy - 一般是未定义的行为(除了POD s);你需要使用构造函数和赋值运算符)

没有“放置删除”,但您可以显式运行析构函数:obj->~Object(),之后obj指针所指向的对象的任何使用都是{{ 3}}。

  

现在,我想知道该代码是否可以在没有任何标准C ++库的情况下运行。

它可能比你所相信的要难得多。您需要了解编译器所针对的ABI的所有细节,这很难。

请注意,正确地运行 <{em> undefined behavior(和constructors) - 对于C ++来说是至关重要的。实际上,它们特别是初始化(隐式)destructors字段[s],没有它,你的对象就会崩溃(只要调用任何virtual成员函数或析构函数)。

另请阅读vtable(适用于C ++ 11)。

用C ++编写自己的内核实际上需要了解有关C ++实现(和ABI)的许多细节。

注意:实际上,使用memcpy智能指针的std::stream进行按位复制,std::mutex - s,std::thread - es,std::string - s - 甚至可能标准集装箱和this. - 等等......很可能会造成灾难。如果你敢做这么糟糕的事情,你真的需要查看你的特定实现的细节......

答案 1 :(得分:2)

除了已经说过的其他答案之外,您可能需要重载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 );
}

然后,如有必要,可以通过调用KMalloc()KFree()例程以及放置new所需的所有构造函数来完成以下代码。

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';