Domanda

Per quanto posso dire, asprintf chiama malloc. Se sostituisco malloc con la Boehm GC, una chiamata a asprintf chiama ancora il malloc tradizionale - almeno questo è quello che valgrind mi dice:

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

E qui è il rapporto 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)

Ecco il codice in cui la chiamata malloc viene da:

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

Una soluzione potrebbe essere quella di utilizzare asprintf, quindi utilizzare malloc per copiarlo in modo che la macro malloc si utilizza invece la funzione 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;
}

Questo sembra sciocco - si tratta di un gruppo di copia inutile e anche sembra essere un mal di codice occhio IHMO. Quindi non v'è un modo sicuro da usare asprintf e altre librerie di sistema che potremmo chiamare il malloc nativa pur utilizzando il Boehm GC? Esiste un'alternativa a asprintf che dovrei usare, invece?

È stato utile?

Soluzione

snprintf restituisce il numero di caratteri che sarebbero stati scritti era la condizione di buffer abbastanza stato grande. Si potrebbe chiamare questo metodo per due volte (una volta per ottenere la dimensione del buffer a destra e poi di nuovo con un buffer sufficientemente grande per ottenere l'output), tuttavia questo è destinata probabilmente ad essere meno efficiente di copiare l'output di asprintf in un buffer da collezione. Ecco un esempio contenente codice che alloca un buffer sufficientemente grande da contenere il valore massimo di un unsigned lungo per sistemi a 32 bit. Nei sistemi in cui non c'è abbastanza spazio, il buffer viene riallocato e riformattato.

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

Altri suggerimenti

questa pagina , è possibile compilare libgc ( la libreria Boehm-gc) con

-DREDIRECT_MALLOC=GC_malloc -DIGNORE_FREE

che dovrebbe intercetta la chiamata a malloc in asprintf. NB:. Non ho provato questo

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top