2012-04-04 2 views
0
gcc (GCC) 4.6.3 
c89 
apache runtime portable libraries 

Bonjour,déclarant la mémoire en utilisant malloc

Juste une question simple, je suppose que je suis en train de créer une valeur UUID.

Je veux une fonction qui le crée pour être autonome (boîte noire) donc je peux juste passer un tampon et la fonction fera le reste.

Ce qui signifie que je dois déclarer la mémoire sur le tas dans cette fonction, car la fonction appelante ne sait pas grand-chose à déclarer. Je sais que c'est une mauvaise idée, car le callie devra libérer la mémoire une fois qu'il a fini avec elle.

Y at-il un moyen de faire mieux?

Lorsque je lance ceci, le branch_id_buf est toujours nul après le retour de la fonction. Cependant, je l'ai passé à la fonction ne devrait donc pas être nul lorsque la fonction retourne car il devrait pointer vers une mémoire allouée.

Un grand merci pour tous les conseils,

static void g_get_branch_id(char *branch_id_buf); 

int main(void) 
{ 
    char *branch_id_buf = NULL; 

    g_get_branch_id(branch_id_buf); 

    printf("branch id [ %s ]\n", branch_id_buf); 

    free(branch_id_buf); 

    return 0; 
} 

static void g_get_branch_id(char *branch_id_buf) 
{ 
    apr_uuid_t uuid; 

#define MAGIC_COOKIE_LENGTH 9 

    const char *MAGIC_COOKIE = "z9hG4bk-"; 
    const int BRANCH_ID_LENGTH = APR_UUID_FORMATTED_LENGTH + MAGIC_COOKIE_LENGTH; 

    branch_id_buf = malloc(BRANCH_ID_LENGTH); 
    if(branch_id_buf == NULL) { 
     return; 
    } 

    strncpy(branch_id_buf, MAGIC_COOKIE, BRANCH_ID_LENGTH); 
    printf("branch id [ %s ]\n", branch_id_buf); 
    apr_uuid_get(&uuid); 

#define PREFIX_BRANCH_LENGTH 8 
    apr_uuid_format(branch_id_buf + PREFIX_BRANCH_LENGTH, &uuid); 

    printf("branch id [ %s ]\n", branch_id_buf); 
} 
+0

Êtes-vous sûr de ne pas manquer de ressources lors de l'exécution de ce programme? – fduff

+0

que se passe-t-il si vous faites un seul pas dans g_get_branch_id()? – fduff

Répondre

1

Généralement, c'est une très mauvaise idée d'allouer dans un module et libre dans un autre. C'est exactement comme cela que vous créez de nombreuses fuites de mémoire dans vos programmes. Votre code est particulièrement problématique, car vous laissez non seulement la liberté à l'appelant, mais aussi la responsabilité d'initialiser le pointeur sur NULL

Cela étant dit, il semble que vous ne traitiez que des constantes de compilation (?), donc je ne comprends pas pourquoi vous avez même besoin de malloc. Tu ne peux pas faire comme ça? La longueur du tableau dans le prototype indique à l'appelant qu'il doit passer un pointeur vers un tampon de cette longueur. Malloc retournera NULL s'il n'a pas réussi à allouer de la mémoire

+0

Merci, ça m'a beaucoup aidé. – ant2009

3

Dans le code affiché, branch_id_buf est locale à la fonction: toutes les modifications apportées ne seront pas visibles à l'appelant.

Vous devez passer un char**:

char *branch_id_buf = NULL; 

g_get_branch_id(&branch_id_buf); 

... 

void g_get_branch_id(char **branch_id_buf) { 

    /* Dereference 'branch_id_buf' within this function. */ 
    *branch_id_buf = malloc(BRANCH_ID_LENGTH); 

EDIT:

Comme commenté par larsmans, envisager de revenir un char* plutôt que d'accepter un argument:

char *branch_id_buf = g_get_branch_id(); 

char* g_get_branch_id() { 

    char* branch_id_buf = malloc(BRANCH_ID_LENGTH); 
    ... 
    return branch_id_buf; 
} 
+1

Étant donné que la fonction renvoie actuellement 'void', il vaut mieux renvoyer un' char * 'dans la mémoire allouée. –

+0

Merci, j'ai pensé au pointeur vers le pointeur. Mais peut-être juste un peu regardé ça. – ant2009

+1

@larsmans, d'accord. – hmjd

2

Is est pas un mauvaise idée. Faites attention et souvenez-vous de libérer ce souvenir. Il y a peu de techniques communes pour le rendre encore plus sûr; comme le compte de référence ou les pools de publication.

Vous pouvez également appeler votre "boîte noire" deux fois. Premier appel pour faire combien de mémoire vous aurez besoin, puis second appel avec un pointeur vers le tampon déjà alloué.

+0

Cela me semble une bonne idée, mais une fonction d'initialisation pour obtenir la taille complète dont j'ai besoin. – ant2009

+0

Cependant, comme il s'agit juste d'une fonction, je devrais également mettre les constantes. Je pense que je serais dupliqué les constantes. Quelque chose que je ne suis pas désireux de faire. Et je ne veux pas les mettre dans un fichier d'en-tête. – ant2009

+0

Vous pouvez appeler sprintf (NULL, "% d", 10000); pour obtenir la longueur (-1) de la chaîne assez longtemps pour stocker "10000". Ceci est un exemple de ma deuxième pensée. – jacekmigacz

Questions connexes