DUE TO SPAM, SIGN-UP IS DISABLED. Goto Selfserve wiki signup and request an account.
...
| Code Block |
|---|
bool test = true; |
| Code Block |
int main(int argc, char **argv)
{
printf("test: %i\n", test);
test = false;
printf("test: %i\n", test);
return 0;
}
|
...
One way to support multiple copies of an in-FLASH program is to move all global variables into a structure. If the amount of memory need for global variables is small, then each main() could simply allocate a copy of that structure on the stack. In the simple example above, this might be:
| Code Block |
|---|
struct my_globals_s { bool test; } |
| Code Block |
int main(int argc, char **argv) { struct my_globals_s my_globals = { true }; |
| Code Block |
printf("test: %i\n", my_globals.test); my_globals.test = false; printf("test: %i\n", my_globals.test); return EXIT_SUCCESS; } |
A pointer to the structure containing the allocated global variables would then have to passed as a parameter to every internal function that needs access to the global variables. So you would change a internal function like:
...
If the size of the global variable structure is large, then allocating the instance on the stack might not be such a good idea. In that case, it might be better to allocate the global variable structure using malloc(). But don't forget to free() the allocated variable structure before exiting! (See the following Memory Clean-Up discussion).
| Code Block |
|---|
struct my_globals_s { bool test; } |
| Code Block |
int main(int argc, char **argv) { FAR struct my_globals_s *my_globals; |
| Code Block |
my_globals = (FAR struct my_globals_s *)malloc(sizeof(struct my_globals_s)); if (my_globals = NULL) { fprintf(stderr, "ERROR: Failed to allocate state structure\n"); return EXIT_FAILURE; } |
| Code Block |
my_globals=>test = true; printf("test: %i\n", my_globals->test); my_globals=>test = false; printf("test: %i\n", my_globals->test); |
| Code Block |
free(my_globals); return EXIT_SUCCESS; } |
Memory Clean-Up
Linux Process Exit
...
There are ways that you could associate allocated memory with a task so that it could cleaned up when the task exits. That approach has been rejected, however, because (1) it could not be done reliably, and (2) it would add a memory allocation overhead that would not be acceptable in context where memory is constrained. Below is the full text from the top-level TODO list coped on 2016-08-15:
| Code Block |
|---|
Title: FREE MEMORY ON TASK EXIT Description: Add an option to free all memory allocated by a task when the task exits. This is probably not be worth the overhead for a deeply embedded system. There would be complexities with this implementation as well because often one task allocates memory and then passes the memory to another: The task that "owns" the memory may not be the same as the task that allocated the memory. Update. From the NuttX forum: ...there is a good reason why task A should never delete task B. That is because you will strand memory resources. Another feature lacking in most flat address space RTOSs is automatic memory clean-up when a task exits. That behavior just comes for free in a process-based OS like Linux: Each process has its own heap and when you tear down the process environment, you naturally destroy the heap too. But RTOSs have only a single, shared heap. I have spent some time thinking about how you could clean up memory required by a task when a task exits. It is not so simple. It is not as simple as just keeping memory allocated by a thread in a list then freeing the list of allocations when the task exists. It is not that simple because you don't know how the memory is being used. For example, if task A allocates memory that is used by task B, then when task A exits, you would not want to free that memory needed by task B. In a process-based system, you would have to explicitly map shared memory (with reference counting) in order to share memory. So the life of shared memory in that environment is easily managed. I have thought that the way that this could be solved in NuttX would be: (1) add links and reference counts to all memory allocated by a thread. This would increase the memory allocation overhead! (2) Keep the list head in the TCB, and (3) extend mmap() and munmap() to include the shared memory operations (which would only manage the reference counting and the life of the allocation). Then what about pthreads? Memory should not be freed until the last pthread in the group exists. That could be done with an additional reference count on the whole allocated memory list (just as streams and file descriptors are now shared and persist until the last pthread exits). I think that would work but to me is very unattractive and inconsistent with the NuttX "small footprint" objective. ... Other issues: |
- Memory free time would go up because you would have to remove
| Code Block |
|---|
- Memory free time would go up because you would have to remove the memory from that list in free(). |
- There are special cases inside the RTOS itself. For example,
| Code Block |
|---|
- There are special cases inside the RTOS itself. For example, if task A creates task B, then initial memory allocations for task B are created by task A. Some special allocators would be required to keep this memory on the correct list (or on no list at all). Updated 2016-06-25: For processors with an MMU (Memory Management Unit), NuttX can be built in a kernel mode. In that case, each process will have a local copy of its heap (filled with sbrk()) and when the process exits, its local heap will be destroyed and the underlying page memory is recovered. So in this case, NuttX work just link Linux or or *nix systems: All memory allocated by processes or threads in processes will be recovered when the process exists. But not for the flat memory build. In that case, the issues above do apply. There is no safe way to recover the memory in that case (and even if there were, the additional overhead would not be acceptable on most platforms). This does not prohibit anyone from creating a wrapper for malloc() and an atexit() callback that frees memory on task exit. People are free and, in fact, encouraged, to do that. However, since it is inherently unsafe, I would never incorporate anything like that into NuttX. Status: Open. No changes are planned. Priority: Medium/Low, a good feature to prevent memory leaks but would have negative impact on memory usage and code size. |