“Tcl_Free()”与“Free()”有何不同?

“Tcl_Free()”与“Free()”有何不同?,c,tcl,C,Tcl,这些描述似乎几乎完全相同。这两者之间有没有需要注意的细微差别?为什么有人会用一个而不是另一个?对于Tcl_Alloc()和malloc()也可能会提出这个问题,因为Tcl支持使用一个工具链在Windows上构建,并加载使用不同工具链构建的DLL。该场景的一个关键特性是,不同的工具链有自己的C库实现是很常见的,这意味着malloc()的不同实现。您必须将malloc()和free()匹配到同一个库,否则通过提供Tcl\u Alloc和Tcl\u free(通常是非常薄的包装)会出现一些真正奇怪的故

这些描述似乎几乎完全相同。这两者之间有没有需要注意的细微差别?为什么有人会用一个而不是另一个?对于
Tcl_Alloc()
malloc()

也可能会提出这个问题,因为Tcl支持使用一个工具链在Windows上构建,并加载使用不同工具链构建的DLL。该场景的一个关键特性是,不同的工具链有自己的C库实现是很常见的,这意味着
malloc()
的不同实现。您必须将
malloc()
free()
匹配到同一个库,否则通过提供
Tcl\u Alloc
Tcl\u free
(通常是非常薄的包装)会出现一些真正奇怪的故障(崩溃、内存泄漏等)它使用户代码能够正确地匹配分配和发布。

之所以使用它们,是因为Tcl支持使用一个工具链在Windows上构建,并加载使用不同工具链构建的DLL。该场景的一个关键特性是,不同的工具链有自己的C库实现是很常见的,这意味着
malloc()
的不同实现。您必须将
malloc()
free()
匹配到同一个库,否则通过提供
Tcl\u Alloc
Tcl\u free
(通常是非常薄的包装)会出现一些真正奇怪的故障(崩溃、内存泄漏等)这使得用户代码能够正确匹配分配和发布。

这通常是最明显的原因:

通常,使用您自己版本的内存分配函数的最好理由是有一个单一的定义,允许您为不同的分配器更改内存分配器。(调试、扩展或使用安全选项实现等)

假设您有以下实现:

void *my_malloc(size_t siz)
{
    return malloc(siz);
}

void my_free(void *ptr)
{
    free(ptr);
}
定义于
分配器\u malloc.c

对于特殊客户X,您已经获得了新ACME分配器的许可证。对于该客户,您可以将可执行文件链接到文件
allocator\u ACME.c
,该文件包含:

void *my_malloc(size_t siz)
{
    return ACME_malloc(siz);
}

void free(void *ptr)
{
    ACME_free(ptr);
}
然后,只需将可执行文件与一个或另一个文件链接,就可以生成标准库
malloc()
的依赖项,或者必须提供
ACME\u malloc()
函数的实现。这样,只需更改多个对象文件中的一个文件,即可将整个依赖项集(假设您在源文件中同时定义了
my_malloc()
my_free()
)更改为多个不同的实现之一

缺点是您有一个级别的函数调用,因此在某些情况下,必须使用一个更可靠的解决方案

假设您购买了一个自动垃圾回收器,因此您不需要返回分配给malloc的内存,就像一些魔术一样,库将检测到您没有更多地使用它,并且它会自动垃圾回收它:

void *my_malloc(size_t siz)
{
    return GC_malloc(siz);
}

void my_free(void *ptr)
{
    /* empty */
}

这通常是最明显的理由:

通常,使用您自己版本的内存分配函数的最好理由是有一个单一的定义,允许您为不同的分配器更改内存分配器。(调试、扩展或使用安全选项实现等)

假设您有以下实现:

void *my_malloc(size_t siz)
{
    return malloc(siz);
}

void my_free(void *ptr)
{
    free(ptr);
}
定义于
分配器\u malloc.c

对于特殊客户X,您已经获得了新ACME分配器的许可证。对于该客户,您可以将可执行文件链接到文件
allocator\u ACME.c
,该文件包含:

void *my_malloc(size_t siz)
{
    return ACME_malloc(siz);
}

void free(void *ptr)
{
    ACME_free(ptr);
}
然后,只需将可执行文件与一个或另一个文件链接,就可以生成标准库
malloc()
的依赖项,或者必须提供
ACME\u malloc()
函数的实现。这样,只需更改多个对象文件中的一个文件,即可将整个依赖项集(假设您在源文件中同时定义了
my_malloc()
my_free()
)更改为多个不同的实现之一

缺点是您有一个级别的函数调用,因此在某些情况下,必须使用一个更可靠的解决方案

假设您购买了一个自动垃圾回收器,因此您不需要返回分配给malloc的内存,就像一些魔术一样,库将检测到您没有更多地使用它,并且它会自动垃圾回收它:

void *my_malloc(size_t siz)
{
    return GC_malloc(siz);
}

void my_free(void *ptr)
{
    /* empty */
}
从手册页:这些过程为内存分配提供了一个独立于平台和编译器的接口。因此,它也可能被移植到不支持
malloc()
接口而不更改源代码的平台。实际上,在大多数平台上,它可能只调用
malloc()
。或者,它还可以额外收集内存统计信息:当Tcl和所有调用Tcl的模块在定义了Tcl_MEM_DEBUG的情况下编译时,这些宏被重新定义为这些过程的特殊调试版本。从主页上看:这些过程为内存分配提供了独立于平台和编译器的接口。因此,它也可能被移植到不支持
malloc()
接口而不更改源代码的平台。实际上,在大多数平台上,它可能只调用
malloc()
。或者,它还可以另外收集内存统计信息:当编译Tcl和所有调用Tcl的模块时,定义了Tcl_MEM_DEBUG,但是,这些宏被重新定义为这些过程的特殊调试版本。