J'écris un logiciel embarqué pour STM32F7 et ma libc est newlib-2.4.0.20160527.malloc() dans newlib: gaspille-t-il de la mémoire après une grosse erreur?
J'ai mis en _sbrk()
comme suit:
extern intptr_t g_bss_end; /* value after the last byte in .bss */
extern intptr_t g_msp_lim; /* stack buffer starts at this address */
intptr_t _sbrk(ptrdiff_t heap_incr)
{
static intptr_t heap_end = 0;
intptr_t prev_heap_end;
intptr_t new_heap_end;
if(heap_end == 0) {
heap_end = (intptr_t)&g_bss_end;
}
prev_heap_end = heap_end;
new_heap_end = prev_heap_end + heap_incr;
if(new_heap_end >= g_msp_lim) {
errno = ENOMEM;
return -1;
}
heap_end = new_heap_end;
return prev_heap_end;
}
Puis, quand je fais ce qui suit:
/* total capacity of my heap is 0x40000 */
void * mem = malloc(0x40000);
free(mem); mem = 0;
mem = malloc(0x40000);
tout fonctionne bien (à savoir, malloc retourne deux fois non nul).
Mais quand je fais ce qui suit (à des fins de test):
for(int32_t sz = 0x50000; sz >= 0; sz--) {
void * mem = malloc(sz);
if(mem != 0) {
__BKPT();
free(mem);
break;
}
}
chaque malloc()
échoue, même malloc(0)
(à savoir, __BKPT()
est jamais atteint). Donc, il n'y a pas de mémoire allouée sur le tas en fait (je n'ai pas eu mem != 0
donc je ne peux même pas free()
quelque chose) et il n'y a pas non plus de mémoire disponible.
Je me attendais malloc()
à l'échec pour chaque sz > 0x40000
et réussir à chaque sz <= 0x40000
(en supposant free()
fonctionne très bien après chaque malloc()
).
Ai-je manqué quelque chose, ou est-ce un bug ou un comportement prévu dans newlib?
Que dit le débogueur? Avez-vous franchi le code? Remarque: l'utilisation de l'allocation de mémoire dynamique à base de tas comme 'malloc' dans les systèmes embarqués est le plus souvent une mauvaise idée et rejetée par de nombreuses normes de codage pour de bonnes raisons. Comportement notablement déterministe et allocation garantie. Évaluer l'utilisation de pools ou d'autres mesures comme des variables statiques avant même de penser à 'malloc' etc! – Olaf
Oh, et utilisez la macro 'NULL' avec des pointeurs. '0' comme constante de pointeur nul est valide, mais une mauvaise habitude des programmeurs C++. C++ 11 a introduit 'nullptr' pour de bonnes raisons. (Le vœu C11 les avait suivi) – Olaf
J'ai parcouru mon code (j'ai vérifié les valeurs de 'mem';' __BKPT() 'était aussi un point d'arrêt). Pour entrer dans le code de newlib avec gdb je le recompile avec '-g3 -O0' maintenant. Je veux travailler 'snprintf' qui repose sur' malloc'. Devrais-je commencer à chercher des alternatives 'snprintf'? Je n'ai pas besoin de 'malloc' pour autre chose. –