代码之家  ›  专栏  ›  技术社区  ›  user52804

如何在Boehm GC中使用asprintf?

  •  2
  • user52804  · 技术社区  · 14 年前

    以下是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;
    

    下面是瓦尔格林的报告:

    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调用的源代码:

    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。那么,在仍然使用Boehm GC的情况下,有没有安全的方法来使用asprintf和其他可能调用本地malloc的系统库呢?有没有替代asprintf的方法呢?

    2 回复  |  直到 11 年前
        1
  •  2
  •   dreamlax    14 年前

    snprintf 返回在提供的缓冲区足够大的情况下本应写入的字符数。您可以调用此方法两次(一次以获得正确的缓冲区大小,然后使用足够大的缓冲区再次调用以获得输出),但是这可能比仅复制 asprintf

    #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;
    
        2
  •  -1
  •   Keith Thompson    11 年前

    根据 this page ,您可以使用

    -DREDIRECT_MALLOC=GC_malloc -DIGNORE_FREE
    

    这是应该的 intercept the call 在asprintf给malloc。注:我没试过这个。