我们可以重载malloc()吗?
Posted
技术标签:
【中文标题】我们可以重载malloc()吗?【英文标题】:Can we overload malloc()? 【发布时间】:2013-04-29 03:45:29 【问题描述】:我经历了重载new和delete,我在读一本书,new和malloc em> 是 new 调用构造函数,返回调用变量的类型,第三个区别是我们可以逐类重载 new,而 malloc 不能,有人也可以逐类解释这个类。
【问题讨论】:
we can overload new on class by class basis
-- 这意味着您可以为每种类型自定义构造函数。
好的,那么 malloc 呢??
我们能不能对 malloc 做同样的事情,我的意思是重载 malloc() 作为一个函数,因为我不明白为什么它写在我们不能写在书中?
是这样,我们不需要重载malloc所以我们不这样做,否则可能会出现某种语言错误。
如果我想分配所需的地址,或者可能是分配的返回地址或大小
【参考方案1】:
全局命名空间中的::operator new
可以被替换(覆盖),而不是重载。这会导致使用覆盖而不是标准库提供的函数。并且可以提供my_class::operator new
,这样就可以在new my_class
表达式中使用,这也和重载不同。
重载new
仅在您使用布置new
语法时发挥作用:
new ( memory_pool, 123, other_args ) my_class( constructor_args )
在new
关键字之后的括号中提供额外的参数会导致operator new
的另一个重载被调用,额外的参数附加在size_t
之后指定需要多少内存。
您当然可以像任何其他函数一样重载::malloc
,方法是定义一个接受不同参数的版本:
void *malloc( std::size_t size, allocation_pool &pool );
这只是一个名为malloc
的新函数。但是最好使用明确的std::
限定来调用库函数,并且添加std::malloc
重载将违反库的规则。
您无法替换 std::malloc
。唯一可以替换的函数是::operator new
的标准变体。没有特定于类的malloc
这样的东西,因为它不接受指示哪个类将进入返回的内存块的参数。 malloc
不知道你将如何处理返回的内存;它只是一个字节。
作为程序组织的问题,可能应该给出一个更专业的分配器并将其称为另一个名称,而不是malloc
。如果您需要根据类型调用不同的函数,请使用模板,例如
template< typename allocated >
void *my_allocate( std::size_t sz ); // maybe "sz" param is unnecessary.
您还可以专门化std::allocator< my_class >
及其成员函数allocate
。然后各种标准库工具将调用您的函数,尽管没有自定义 new
。 (由于其怪癖,您可能会避免对自定义 new
过于深入。)
【讨论】:
【参考方案2】:重载new
与constructors
无关。 class
可以提供自己的运算符new()
,它负责在构造函数调用之前分配内存。这对于优化小对象池很有用,例如您还可以查看运算符new()
的各种重载,包括所谓的“新放置”,允许为就地构造(用户提供的缓冲区)、文件/行诊断等提供任意参数。
【讨论】:
好的,所以我想答案是对于 new 的情况,因为在我们知道要分配的大小等情况下,重载可能很有用,因为它将创建对象也。但是在 malloc 中我们不能有类似的优势,因为 malloc 仅限于分配内存,所以我们不需要重载 malloc,有这样做没有必要也没有好处。 @Praveen - 没错,malloc 是“无类型”的,只返回一个 void *,所以真的没有重载的基础。【参考方案3】:注意:您可以不随意“重载”或“覆盖”标准 C 库函数,但通常的做法是允许您覆盖一个合理的子集它。
一般来说,链接器不知道给定的目标文件是用什么语言编写的,它在知识水平显着较低的情况下工作——使用目标文件的外部符号,在所有目标文件中应该是唯一的和共享库被链接在一起,因为链接器本身不能随意删除在其命令行上给出的带有重复符号的对象。 值得注意的例外是静态库 (.a) - 如果有助于删除重复的外部符号,则允许链接器从存档中删除任何项目。
允许重写库函数由两部分组成:
具有将函数标记为可重载的语法的编译器——适当的外部符号将被标记为“弱链接”。例如,对于gcc
:
`__attribute__((weak)) void *malloc(size_t size)`
理解弱链接的动态链接器(ld.so
)。
不知道malloc()
是否在特定共享libc
中被声明为弱符号,但通常是这样,因此您很有可能能够覆盖它,但您的里程可能会有所不同。
【讨论】:
【参考方案4】:是的,我们可以重载标准库函数 malloc。 请看下面的代码sn-p:
#include <iostream>
void malloc(void)
puts("malloc");
int main()
int *p= (int*)malloc(8);
malloc();
free(p);
return 0;
此代码打印 malloc。
另外,下面是该程序内存的TEXT部分的sn-p:
0000000000400744 T _Z6mallocv
0000000000400770 T main
以下是动态符号表中的 sn-p
0000000000000000 DF *UND* 00000000000001d2 GLIBC_2.2.5 malloc
0000000000000000 DF *UND* 00000000000001a5 GLIBC_2.2.5 __libc_start_main
因此,我们可以重载标准库函数,如 c++ 中的 malloc。
【讨论】:
以上是关于我们可以重载malloc()吗?的主要内容,如果未能解决你的问题,请参考以下文章