如何将 asprintf 与 Boehm GC 结合使用?

发布于 2024-09-17 19:01:33 字数 2691 浏览 7 评论 0原文

据我所知,asprintf 调用了malloc。如果我用 Boehm GC 替换 malloc,对 asprintf 的调用仍然会调用传统的 malloc - 至少 valgrind 是这么告诉我的:

这是 malloc 宏:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>

#include <gc.h>
#define malloc(n)    GC_MALLOC(n)
#define calloc(m,n)  GC_MALLOC((m)*(n))
#define realloc(p,n) GC_REALLOC((p),(n))

typedef char * string;

这是 valgrind 报告:

hopcroft:didactic_scheme(flexible_strings) scotttaylor$ valgrind --suppressions=./boehm-gc.suppressions --leak-check=full bin/escheme -e 1
==16130== Memcheck, a memory error detector
==16130== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==16130== Using Valgrind-3.6.0.SVN and LibVEX; rerun with -h for copyright info
==16130== Command: bin/escheme -e 1
==16130== 
--16130-- bin/escheme:
--16130-- dSYM directory is missing; consider using --dsymutil=yes
1==16130== 
==16130== HEAP SUMMARY:
==16130==     in use at exit: 4,312 bytes in 3 blocks
==16130==   total heap usage: 3 allocs, 0 frees, 4,312 bytes allocated
==16130== 
==16130== 128 bytes in 1 blocks are definitely lost in loss record 2 of 3
==16130==    at 0x100012D75: malloc (vg_replace_malloc.c:236)
==16130==    by 0x1000918EC: asprintf (in /usr/lib/libSystem.B.dylib)
==16130==    by 0x1000013FA: printInt (in bin/escheme)
==16130==    by 0x100001D38: print (in bin/escheme)
==16130==    by 0x100001DC5: main (in bin/escheme)
==16130== 
==16130== LEAK SUMMARY:
==16130==    definitely lost: 128 bytes in 1 blocks
==16130==    indirectly lost: 0 bytes in 0 blocks
==16130==      possibly lost: 0 bytes in 0 blocks
==16130==    still reachable: 4,184 bytes in 2 blocks
==16130==         suppressed: 0 bytes in 0 blocks
==16130== Reachable blocks (those to which a pointer was found) are not shown.
==16130== To see them, rerun with: --leak-check=full --show-reachable=yes
==16130== 
==16130== For counts of detected and suppressed errors, rerun with: -v
==16130== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 66 from 13)

这是 malloc 调用的代码from:

static string printInt(Object self) {
  string str;
  asprintf(&str, "%lu", getValueInt(self));
  return str;
}

解决方法可能是使用 asprintf,然后使用 malloc 复制它 这样就使用了 malloc 宏而不是原始函数:

static string printInt(Object self) {
  string tmp;
  string str;

  asprintf(&tmp, "%lu", getValueInt(self));
  str = calloc(sizeof(string), strlen(tmp) + 1);

  strcpy(str, tmp);
  free(tmp);

  return str;
}

这看起来很愚蠢 - 它涉及一堆不必要的复制,而且碰巧是代码眼痛 IHMO。那么有没有一种安全的方法来使用 asprintf 和其他可能调用本机 malloc 的系统库,同时仍然使用 Boehm GC?我应该使用 asprintf 的替代方案吗?

As far as I can tell, asprintf calls malloc. If I replace malloc with the Boehm GC, a call to asprintf still calls the traditional malloc - at least that's what valgrind is telling me:

Here's the malloc macro:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>

#include <gc.h>
#define malloc(n)    GC_MALLOC(n)
#define calloc(m,n)  GC_MALLOC((m)*(n))
#define realloc(p,n) GC_REALLOC((p),(n))

typedef char * string;

And here is the valgrind report:

hopcroft:didactic_scheme(flexible_strings) scotttaylor$ valgrind --suppressions=./boehm-gc.suppressions --leak-check=full bin/escheme -e 1
==16130== Memcheck, a memory error detector
==16130== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==16130== Using Valgrind-3.6.0.SVN and LibVEX; rerun with -h for copyright info
==16130== Command: bin/escheme -e 1
==16130== 
--16130-- bin/escheme:
--16130-- dSYM directory is missing; consider using --dsymutil=yes
1==16130== 
==16130== HEAP SUMMARY:
==16130==     in use at exit: 4,312 bytes in 3 blocks
==16130==   total heap usage: 3 allocs, 0 frees, 4,312 bytes allocated
==16130== 
==16130== 128 bytes in 1 blocks are definitely lost in loss record 2 of 3
==16130==    at 0x100012D75: malloc (vg_replace_malloc.c:236)
==16130==    by 0x1000918EC: asprintf (in /usr/lib/libSystem.B.dylib)
==16130==    by 0x1000013FA: printInt (in bin/escheme)
==16130==    by 0x100001D38: print (in bin/escheme)
==16130==    by 0x100001DC5: main (in bin/escheme)
==16130== 
==16130== LEAK SUMMARY:
==16130==    definitely lost: 128 bytes in 1 blocks
==16130==    indirectly lost: 0 bytes in 0 blocks
==16130==      possibly lost: 0 bytes in 0 blocks
==16130==    still reachable: 4,184 bytes in 2 blocks
==16130==         suppressed: 0 bytes in 0 blocks
==16130== Reachable blocks (those to which a pointer was found) are not shown.
==16130== To see them, rerun with: --leak-check=full --show-reachable=yes
==16130== 
==16130== For counts of detected and suppressed errors, rerun with: -v
==16130== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 66 from 13)

Here's the code in which the malloc call is coming from:

static string printInt(Object self) {
  string str;
  asprintf(&str, "%lu", getValueInt(self));
  return str;
}

A workaround might be to use asprintf, then use malloc to copy it
so that the malloc macro is used instead of the primitive function:

static string printInt(Object self) {
  string tmp;
  string str;

  asprintf(&tmp, "%lu", getValueInt(self));
  str = calloc(sizeof(string), strlen(tmp) + 1);

  strcpy(str, tmp);
  free(tmp);

  return str;
}

That seems silly - it involves a bunch of unnecessary copying and also happens to be a code eye sore IHMO. So is there a safe way to use asprintf and other system libraries that might call the native malloc while still using the Boehm GC? Is there an alternative to asprintf that I should be using instead?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

岁月如刀 2024-09-24 19:01:33

snprintf 返回如果提供的缓冲区足够大则将写入的字符数。您可以调用此方法两次(一次是为了获取正确的缓冲区大小,然后再次使用足够大的缓冲区来获取输出),但是这可能比仅复制 asprintf 的输出效率低> 进入可收集的缓冲区。下面的示例包含分配足够大的缓冲区以包含 32 位系统的 unsigned long 最大值的代码。在没有足够空间的系统上,缓冲区将被重新分配并重新格式化。

#include <limits.h>

...

unsigned long intValue = getValueInt(self);
size_t maxLength = 11; // heuristic
char *buf = malloc(maxLength);

int result = snprintf(buf, maxLength, "%lu", intValue);
if (result > maxLength)
{
    // shouldn't ever get here, but just in case the buffer is too small
    // we reallocate it to the correct size and try again.
    buf = malloc(result);
    snprintf(buf, result, "%lu", intValue);
}

return buf;

snprintf returns the number of characters that would have been written had the provided buffer been large enough. You could call this method twice (once to get the right buffer size and then again with a buffer large enough to obtain the output), however this is probably going to be less efficient than just copying the output of asprintf into a collectable buffer. Here's an example containing code that allocates a buffer large enough to contain the maximum value of an unsigned long for 32-bit systems. On systems where there is not enough space, the buffer is reallocated and reformatted.

#include <limits.h>

...

unsigned long intValue = getValueInt(self);
size_t maxLength = 11; // heuristic
char *buf = malloc(maxLength);

int result = snprintf(buf, maxLength, "%lu", intValue);
if (result > maxLength)
{
    // shouldn't ever get here, but just in case the buffer is too small
    // we reallocate it to the correct size and try again.
    buf = malloc(result);
    snprintf(buf, result, "%lu", intValue);
}

return buf;
轻拂→两袖风尘 2024-09-24 19:01:33

根据这个页面,可以编译libgc(boehm- gc 库),

-DREDIRECT_MALLOC=GC_malloc -DIGNORE_FREE

应该拦截调用 到 asprintf 中的 malloc。注意:还没有尝试过这个。

According to this page, you can compile libgc (the boehm-gc library) with

-DREDIRECT_MALLOC=GC_malloc -DIGNORE_FREE

which ought to intercept the call to malloc in asprintf. NB: haven't tried this.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文