我们可以重载malloc()吗?

Posted

技术标签:

【中文标题】我们可以重载malloc()吗?【英文标题】:Can we overload malloc()? 【发布时间】:2013-04-29 03:45:29 【问题描述】:

我经历了重载newdelete,我在读一本书,newmalloc 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&lt; my_class &gt; 及其成员函数allocate。然后各种标准库工具将调用您的函数,尽管没有自定义 new。 (由于其怪癖,您可能会避免对自定义 new 过于深入。)

【讨论】:

【参考方案2】:

重载newconstructors 无关。 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()吗?的主要内容,如果未能解决你的问题,请参考以下文章

覆盖和重载 Java

什么是方法重载?可以定义两个同名但参数类型不同的方法吗?

泛型函数的重载可以对其他重载开放吗?

new和malloc的区别

python中有函数重载吗

用了@GetMapping还能写方法重载吗