-
Notifications
You must be signed in to change notification settings - Fork 61
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
realloc fails if extending block in-place crosses the address 0xffff #922
Comments
Hmm, I'm afraid when I wrote malloc I never even remotely considered that devices might have more than 64 KiB of memory … |
Well, external SRAM supported since ATmega103, the very first AVRmega chip. Although using external SRAM isn't exactly common i guess, but if you use it you probably want full 64K because why not. |
Nevertheless, you couldn't address more than 64 KiB of RAM on the ATmega103/128 etc., RAM addresses have only been 16 bits (and part of the external RAM was unusable since it's shadowed by IO registers and internal RAM). |
Umm it doesn't need to be more than 64K of RAM. Call fails each time when block + size_new > 0xffff for example if trying to extend 0x100-byte block at 0xfe80 to 0x200 bytes, realloc fails because 0xfe80+0x200 > 0xffff, even if there's tons of free RAM. I made a workaround for my code by trying malloc if realloc fails but it took some time to figure out because allocator issue wasn't exactly the first thing to suspect :) |
But if your pointer is already at 0xfe80, and you try extending it by 0x200, your region ends up beyond the area that can be addressed by a usual 16-bit pointer, so what's the point? Somehow, I don't get it … to me, that only makes sense if your system can actually address more than 64 KiB – and I am still under the assumption that AVR-GCC could not handle data addresses wider than 16 bits. |
Block (ptr=0xfe80,size=0x100) is a vaild allocated block for 64K memory space. Trying to extend it to size=0x200 without moving of course isn't possible because it crosses the address space end. So valid realloc behavior in this case would be to move data somewhere if there's some space available and return pointer to the new allocated block, not fail immediately. So i guess if wrap detected at line 60 i think it should jump to malloc at line 146 not return NULL |
Ah, now I got it. :-) Thanks for keeping explaing it to me. |
ACK. Some AVRs feature RAMPX/Y/Z/D registers to extend X/Y/Z resp. LDS/STS to 24-bit pointers. But avr-gcc does not support segmented memory like that. Or more correct, RAM pointers are always 16 bits wide, and supporting such RAM would require a default pointer size of 24 bits and thus a considerable re-write of avr-gcc. llvm is no different in that regard. One could support (parts of) upper RAM by means of special address spaces similar to __memx, but it would be PITA and you won't find anyone willing to implement that. That said, the only way to make use of this is by means of dedicated hacks / asm code, e.g. to make use of upprt RAM for some buffer that's managed "by hand". The only "support" for RAMP* is that avr-gcc saves / restores them when they might be clobbered in an ISR. The current issue seems to be that AVR-LibC doesn't handle memory segmentation well, i.e. even though there is enough memory in priciple, realloc fails. |
Check at libc/stdlib/realloc.c#60 causes call to fail if extending block to the new size causes pointer overflow, even if there's plenty of free memory to move data. Instead of returning NULL it should jump to the line 146
The text was updated successfully, but these errors were encountered: