2013-03-11 3 views
2

J'ai une routine d'appeler la fonction gSoap API soap_malloc. Mais le programme me donne un segmentation fault chaque fois que j'essaie d'accéder à la mémoire allouée par soap_malloc. Lorsque j'utilise gdb pour le déboguer. Je trouve que l'intérieur soap_malloc, la valeur de retour stockée dans le registre %rax est 0x7fffec0018f0. Mais au retour, %rax a été remplacé par 0xffffffffec0018f0. Seul le 32 bits inférieur a été conservé, le 32 bits le plus élevé a été remplacé par 1. Et cela conduit à accéder à une adresse qui est assez élevée, donc a entraîné l'arrêt de la routine. Merci à vous tous de me donner des idées sur la façon dont cela peut se produire. Je cours mon programme multi-thread dans Ubuntu12.04 x86-64.Comment la valeur de retour peut-elle être modifiée?

Voilà comment je l'appelle:

void *temp = soap_malloc(soap, 96); 

Et c'est la mise en œuvre soap_malloc (seule la partie else est exécutée et macro SOAP_MALLOC ne fait que passer le second argument de malloc, SOAP_CANARY est constant 0xC0DE):

#ifndef SOAP_MALLOC   /* use libc malloc */ 
# define SOAP_MALLOC(soap, size) malloc(size) 
#endif 

#ifndef SOAP_CANARY 
# define SOAP_CANARY (0xC0DE) 
#endif 

void* soap_malloc(struct soap *soap, size_t n) 
{ register char *p; 
    if (!n) 
    return (void*)SOAP_NON_NULL; 
    if (!soap) 
    return SOAP_MALLOC(soap, n); 
    if (soap->fmalloc) 
    p = (char*)soap->fmalloc(soap, n); 
    else 
    { n += sizeof(short); 
    n += (-(long)n) & (sizeof(void*)-1); /* align at 4-, 8- or 16-byte boundary */ 
    if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(void*) + sizeof(size_t)))) 
    { soap->error = SOAP_EOM; 
     return NULL; 
    } 
    /* set the canary to detect corruption */ 
    *(unsigned short*)(p + n - sizeof(unsigned short)) = (unsigned short)SOAP_CANARY; 
    /* keep chain of alloced cells for destruction */ 
    *(void**)(p + n) = soap->alist; 
    *(size_t*)(p + n + sizeof(void*)) = n; 
    soap->alist = p + n; 
    } 
    soap->alloced = 1; 
    return p; 
} 

Telle est la définition de SOAP_NON_NULL:

static const char soap_padding[4] = "\0\0\0"; 
#define SOAP_NON_NULL (soap_padding) 

Mises à jour (12/03/2013 )
Je déclare explicitement soap_malloc que le retour void * et le problème résolu. Auparavant, la valeur renvoyée est tronquée à int et le bit de signe 1 a été étendu lors de l'attribution du résultat à void *temp.

+0

Pouvez-vous fournir un exemple de code minimal qui reproduit ce problème? –

+0

Dans certains endroits, vous utilisez ** soap_malloc ** dans d'autres applications ** SOAP_MALLOC **. Quelle est la définition de ** SOAP_MALLOC ** ou cette partie de la bibliothèque gSoap? – Jere

+0

@Jere je décris 'SOAP_MALLOC' est une macro qui passe juste le deuxième argument à' malloc'. Désolé pour ça, je vais les éditer dans le corps du code. – leowang

Répondre

3

Est-ce que le code d'appel ont un prototype approprié pour la fonction soap_malloc() portée?

Il semble que le void * soit converti en int, c'est-à-dire le type de retour par défaut. Cela arrive si la fonction n'a pas été correctement déclarée.

+0

désolé, j'aurais dû mettre le code appelant au-dessus de soap_malloc'. Je viens d'utiliser un 'void * temp' pour stocker la valeur de retour. – leowang

+0

@leowang Je ne suis pas certaine de comprendre votre correction ... Cela n'a pas d'importance. Si vous appelez plain old 'malloc()' * sans * y compris l'en-tête comme ceci: 'void * p = malloc (1024)', vous * obtiendrez un résultat 'int'. Le type sur le côté gauche de '= 'n'a pas d'importance. – unwind

+0

Je suis désolé je ne comprends pas. Quelque chose ne va pas avec 'malloc'? Que voulez-vous dire par 'l'en-tête'? – leowang

Questions connexes