Le pointeur passé à free () doit-il pointer vers le début du bloc de mémoire ou peut-il pointer vers l’intérieur?

La question est dans le titre … J’ai cherché mais je n’ai rien trouvé.


Modifier:

Je ne vois pas vraiment la nécessité d’expliquer cela, mais comme les gens pensent que ce que je dis n’a aucun sens (et que je pose les mauvaises questions), voici le problème:

Puisque les gens semblent être très intéressés par la cause “fondamentale” de tout le problème plutôt que par la question posée (puisque cela aide apparemment à mieux résoudre les problèmes, voyons si c’est le cas):

J’essaie de créer une bibliothèque d’exécution D basée sur NTDLL.dll afin de pouvoir utiliser cette bibliothèque pour des sous-systèmes autres que le sous-système Win32. Cela me force donc à ne faire que des liens avec NTDLL.dll.

Oui, je suis conscient que les fonctions sont “non documentées” et peuvent changer à tout moment (même si je parierais cent dollars que wcstombs fera toujours la même chose exactement dans 20 ans, si elle existe toujours). Oui, je sais que les gens (en particulier Microsoft) n’aiment pas les développeurs qui se connectent à cette bibliothèque et que je serai probablement critiqué pour le droit ici. Et oui, ces deux points ci-dessus signifient que des programmes tels que chkdsk et les défragmenteurs exécutés avant le sous-système Win32 ne sont même pas supposés être créés en premier lieu, car il est littéralement impossible de créer un lien avec kernel32.dll ou msvcrt.dll et Nous avons toujours des exécutables natifs NT, donc nous, les développeurs, devons simplement prétendre que ces étapes sont censées restr pour toujours hors de notre scope.

Mais non , je doute que tout le monde ici souhaite que je colle quelques milliers de lignes de code et qu’il m’aide à les parcourir et à essayer de comprendre pourquoi les allocations de mémoire qui ne manquent pas sont rejetées par le code source que je modifie. C’est pourquoi j’ai posé une question sur un problème différent de la cause “fondamentale”, même si ce dernier est censé être la meilleure pratique de la communauté.

Si cela ne vous dit rien, n’hésitez pas à poster des commentaires ci-dessous! 🙂


Edit 2:

Après environ 8 heures de débogage, j’ai finalement trouvé le problème:

Il s’avère que RtlReAllocateHeap() ne fonctionne pas automatiquement comme RtlAllocateHeap() si le pointeur qui lui est atsortingbué est NULL .

Il doit pointer vers le début du bloc. Il est prudent de passer un pointeur null à free() , mais le passage de tout pointeur non alloué par malloc() ou l’un de ses parents entraînera un comportement indéfini. Certains systèmes vous donneront une erreur d’exécution – quelque chose du genre “Dévocation du pointeur non mallocé”.

Modifier:

J’ai écrit un programme de test pour obtenir le message d’erreur. Sur ma machine, ce programme:

 #include  int main(int argc, char **argv) { int *x = malloc(12); x++; free(x); return 0; } 

Crashes avec ce message:

 app(31550) malloc: *** error for object 0x100100084: pointer being freed was not allocated 

La seule chose que vous pouvez passer à free est un pointeur qui vous a été renvoyé par malloc (ou calloc , realloc , etc.) ou par NULL.

Je suppose que vous posez la question parce que vous avez une fonction dans laquelle vous faites un malloc, et vous voulez manipuler le bloc de données, puis vous en débarrasser lorsque vous avez terminé, et vous ne voulez pas être dérangé. une copie du pointeur d’origine autour. Ça ne marche pas comme ça.

D’après les commentaires que vous avez ajoutés aux réponses existantes, il semble que vous posiez la mauvaise question. Si vous avez besoin d’alignement de mémoire, pourquoi ne posez-vous pas cette question? Renseignez-vous sur le problème fondamental plutôt que sur votre solution perçue!

Donc, si cela ne vous dérange pas, je vais répondre à la question que vous auriez dû poser:

L’allocation de mémoire _aligned_malloc() est prise en charge dans Win32 par _aligned_malloc() . C’est plus de moins équivalent à POSIX memalign()

Si vous avez besoin d’une implémentation d’allocation alignée, il est assez simple d’implémenter:

 void* aligned_malloc( size_t size, size_t alignment ) { void* unaligned = malloc( size + alignment ) ; void* aligned = (void*)(((intptr_t)unaligned + alignment) & ~(alignment - 1)); void** free_rec_ptr = ((void**)aligned - 1) ; *free_rec_ptr = unaligned ; return aligned ; } void aligned_free( void* block ) { void** free_rec_ptr = ((void**)block - 1) ; free( *free_rec_ptr ) ; } 

L’argument d’ alignment doit être une puissance de deux.

FWIW, la dernière fois que j’ai étudié la façon dont la bibliothèque d’exécution C fonctionnait avec malloc et free , le bloc que malloc vous donne contient en fait quelques mots supplémentaires avec des décalages négatifs par rapport au pointeur qu’il vous donne. Ceux-ci disent des choses comme la taille du bloc et d’autres choses. free comptait sur pouvoir trouver ces choses. Je ne sais pas si cela nous éclaire.