编译器或标准C++库 - 新建和删除
Compiler or Standard C++ Library - new and delete
我正在为没有任何库的软件(内核)开发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 new
和operator 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';
- 创建模板类型而不新建/删除
- C++ 在请求特定字节的新建后删除
- 为什么非放置"新建"和"删除"内置于语言中,而不仅仅是常规函数?
- 来自C#的mingw DLL:为什么我必须覆盖新建/删除?
- C++ - 定义自定义新建和删除运算符时make_shared
- 使用安全零内存新建/删除时出现问题
- 奇怪的内存泄漏由C++中的新建/删除
- CRT 检测到应用程序在堆缓冲区(新建/删除)类结束后写入内存
- 无法覆盖C++中纯抽象类中的运算符删除/新建
- 混合运算符和表达式新建/删除
- 使用运算符重载(新建/删除)实现单例的优缺点
- 忽略全局覆盖的新建/删除
- 基本的新建/删除操作员日志记录
- C++自定义全局新建/删除覆盖系统库
- Realloc 和全球本地新建/删除运算符覆盖
- 使用 malloc/free 来模拟新建/删除
- 新建/删除运算符不匹配错误的严重程度
- 新建/删除导致访问冲突
- 新建/删除操作符重载和基类
- 新建/删除/免费存储和 malloc/免费/堆组合