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

Compiler or Standard C++ Library - new and delete

本文关键字:新建 删除 标准 C++ 编译器      更新时间:2023-10-16

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

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

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

您首先应该定义您针对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();

第二条语句使用 C++ 的放置新功能,它将在作为放置传递的(或多或少"单元化")内存区域上运行构造函数。

(请注意,C++对象的按位复制 - 例如带有memcpy- 通常是未定义的行为(POD 除外);您需要使用构造函数和赋值运算符)

没有"放置删除",但您可以显式运行析构函数:obj->~Object()之后,对obj指针指向的对象的任何使用都是未定义的行为。

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

这可能比你想象的要难得多。您需要了解编译器针对的 ABI 的所有详细信息,这很难。

请注意,足够好的顺序正确运行构造函数(和析构函数)对C++至关重要;实际上,它们正在初始化(隐式)vtable字段,否则您的对象可能会崩溃(一旦调用任何virtual成员函数或析构函数)。

另请阅读有关五法则(C++11)的信息。

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

注意:实际上,按位复制,memcpy智能指针,std::stream-s,std::mutex-es,std::thread-s - 甚至可能是标准容器和std::string-s等...- 很可能造成灾难。如果你敢做这种坏事,你真的需要研究你的特定实现的细节......

除了其他答案已经说过的内容之外,您可能还希望重载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';