Вопрос

Насколько я могу сказать, Asprintf называет Malloc. Если я заменил MALLOC с Boehm GC, вызов 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 исходит от:

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;
}

Это кажется глупо - это включает в себя кучу ненужных копирований, а также оказывается кодовым глазом Sore IHMO. Таким образом, есть ли безопасный способ использовать AsprintF и другие системные библиотеки, которые могут позвонить на родной Malloc, пока все еще используя Boehm GC? Есть ли альтернатива Asprintf, что я должен использовать вместо этого?

Это было полезно?

Решение

snprintf Возвращает количество персонажей, которые были бы написаны, имел бы предоставленный буфер был достаточно большим. Вы можете назвать этот метод дважды (один раз, чтобы получить правильный размер буфера, а затем снова с буфером достаточно большой, чтобы получить вывод), однако это, вероятно, будет быть менее эффективным, чем просто копирование вывода asprintf в коллекционный буфер. Вот пример, содержащий код, который выделяет буфер, достаточно большой, чтобы содержать максимальное значение unsigned Long для 32-битных систем. О системах, где недостаточно места, буфер перераспределяется и перераспределяется.

#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;

Другие советы

Согласно с эта страница, вы можете компилировать Libgc (библиотека Boehm-GC) с

-DREDIRECT_MALLOC=GC_malloc -DIGNORE_FREE

что следует перехватить звонок в Malloc в Asprintf. NB: не пробовал это.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top