2017-08-20 7 views
1

Je suis en train d'allouer la mémoire avec mmap, voici le code:retours d'allocation mmap 0xfffffffffffffff4 (non MAP_FAILED)

long long *copy; 
copy = (long long*)mmap(NULL, 
         (size_t)1024, 
         PROT_READ | PROT_WRITE | PROT_EXEC, 
         MAP_PRIVATE | MAP_ANON, -1, 0); 

    if (copy == MAP_FAILED) { 
    fprintf(stderr, "Memory allocation failed (Process aborted)\n"); 
    exit(1); 
    } 
    printf("Pointer: %p\n", copy); 

Il est évident que je vérifie si l'allocation échoue. Lorsque cela se produit, je devrais obtenir -1 à partir de ce que je rassemble du man pages. La chose est que je reçois -12, bien 0xfffffffffffffff4, donc l'erreur n'est pas attrapée et le programme continue. Je pensais que c'est peut-être à cause de la distribution (long long*), mais une distribution ne devrait pas changer la valeur du pointeur. Je suis donc très curieux de savoir pourquoi cela arrive et comment l'empêcher.

Plus étrange comportement:

J'ai essayé d'imprimer le errno. Si j'utilise printf("%d\n", errno);, il imprime 0 et le pointeur est toujours défini sur 0xfffffffffffffff4. Mais si je l'utilise err(errno, "%p", copy); il imprime:

program.exe: 0x7f8130981000: Success 

Et maintenant, le pointeur est valide, mais je ne peux pas l'utiliser parce que l'exécution err terminé.

+0

'program.exe' - êtes-vous sur Windows? Utilisez-vous MinGW ou Cygwin ou autre chose? –

+0

Non je peux voir comment cela peut être trompeur, je suis sur linux mais je spécifie l'extension .exe à des fins d'organisation – Hadron

+2

Votre problème pourrait bien être la distribution du retour de 'mmap'. En C, ceci n'est jamais nécessaire et peut cacher des bogues. Peut-être que vous avez oublié de '#include '? Peut-être que vous n'avez pas changé tous les avertissements? '-Wall' pourrait vous en dire plus. –

Répondre

0

Lors de la compilation avec tous les avertissements (-Wmissing-prototypes -Wstrict-prototypes -Werror -Wextra), comme suggéré dans les commentaires, j'ai réalisé que <err.h> n'était pas inclus. Quand je l'ai inclus, le «comportement étrange» que j'ai décrit à la fin de ma question a disparu; le programme s'est comporté normalement mais toujours avec un mauvais pointeur, je ne le savais pas mais à ce stade le programme aurait fonctionné si je n'ai pas vérifié le errno.

Dans d'autres parties du code, j'ai des fonctions d'assemblage qui ont toujours bien fonctionné (c'est pourquoi je pensais que l'erreur ne leur était pas liée). Mais alors je me souviens que certains d'entre eux utilisent %rbx pour transmettre des informations entre eux, mais il se trouve que %rbx est le registre utilisé pour errno dans gcc. Donc, en regardant le code d'assemblage généré pour cette fonction, j'ai réalisé %rbx n'était pas "protégé" par le compilateur. Ajoutant aux en-têtes <errno.h> fixe cela, et maintenant tout fonctionne bien.

Même s'il semble fonctionner sans les inclusions correctes, ceci est certainement une leçon pour être plus prudent et toujours utiliser les options d'avertissement maximum.

+0

Qu'entendez-vous par" n'était pas protégé "? 'rbx' est un registre sauvegardé et il vous appartient de le sauvegarder et de le restaurer si vous l'utilisez dans un assemblage écrit à la main. Vous devriez le savoir avant d'écrire l'assembleur à la main. – Art

+0

La chose est que cela fonctionne maintenant que tous les fichiers d'en-tête corrects ont été inclus (et les fonctions de l'assembleur n'ont pas changé). Je ne sais pas pourquoi. J'ai remarqué que lorsque les fichiers corrects avaient été inclus, '% rsp' était décrémenté de quelques octets de plus avant l'appel de' mmap() ', il y avait peut-être un problème d'écrasement. – Hadron