Pregunta

Por lo que yo puedo decir, asprintf llama a malloc. Si sustituyo malloc con el Boehm GC, una llamada a asprintf todavía llama la malloc tradicional - al menos eso es lo que me está diciendo valgrind:

Aquí está la macro 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;

Y aquí está el informe 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)

Este es el código en el que la llamada malloc proviene de:

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

Una solución podría ser utilizar asprintf, a continuación, utilizar malloc para copiarlo de modo que la macro malloc se utiliza en lugar de la función primitiva:

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

Esto parece tonto - se trata de un montón de copias innecesarias y también pasa a ser un dolor de ojos código IHMO. Entonces, ¿hay una forma segura de usar asprintf y otras bibliotecas del sistema que podrían llamar a la malloc nativa sin dejar de utilizar el Boehm GC? ¿Existe una alternativa a asprintf que yo debería usar en su lugar?

¿Fue útil?

Solución

snprintf devuelve el número de caracteres que se han escrito había proporcionado el búfer sido lo suficientemente grande. Se podría llamar a este método dos veces (una vez para obtener el tamaño del búfer de la derecha y luego de nuevo con un gran suficiente tampón para obtener la salida), sin embargo esto es probablemente va a ser menos eficiente que sólo copiar la salida de asprintf en un búfer de colección. He aquí un ejemplo que contiene código que asigna un búfer suficientemente grande para contener el valor máximo de un unsigned long para sistemas de 32 bits. En sistemas donde no hay suficiente espacio, el buffer se reasigna y reformateado.

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

Otros consejos

De acuerdo con esta página , puede compilar libgc ( la biblioteca boehm-gc) con

-DREDIRECT_MALLOC=GC_malloc -DIGNORE_FREE

interceptar la llamada a malloc en asprintf. NB:. No he probado esto

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top