3 ms·
> is_alloc: If you have to call is_alloc because you don't know and you get `true` back, you still don't know anything, it could be your memory is live or it co
by bArray 4y ago
> is_alloc: If you have to call is_alloc because you don't know and you get `true` back, you still don't know anything, it could be your memory is live or it could be something else was allocated over your stale pointer.
The answer I want is a simple one - is _this_ pointer currently pointing to somewhere with allocated memory? The goal would be to avoid double free, or double allocating (and therefore memory leaks).
> free_all: This is just ridiculous. Now the heap is completely unusable because your memory could be freed from under you at any time by a concurrent free_all.
I think you misunderstand. You could have a (contrived) structure like:
typedef struct{ char* a, char** b } s;
You then have the following allocations (not tested):
s* data = (s*)malloc(sizeof(s));
data->a = (char*)malloc(n * sizeof(char));
data->b = (char**)malloc(l * sizeof(char*));
for(int x = 0; x < l; x++) data->b[x] = (char*)malloc(n * sizeof(char));
Rather than free each of these allocations individually, you would instead have `free_all(data)` (might not be a great name). At compile time the compiler would look at the structure and expand out to be all the free operations as required. Of course you would need the `is_alloc` to test if somebody actually did allocate memory.
I would then imagine a common pattern would be:
s* data = NULL; // Indicate we point to nothing
/* Allocate */
free_all(data); // Free associated memory
data = NULL; // Indicate no memory allocated
Of course one trap would be:
s* data = (s*)malloc(sizeof(s));
data->a = y;
data->b = z;
free_all(data);
Then one would have to consider whether y and z and free'd or not.
- mike_hock 4y ago> is _this_ pointer currently pointing to somewhere with allocated memory? The goal would be to avoid double free, or double allocating This doesn't work because you don't know who allocated that memory. Thread A: free(p) Thread B: malloc(...) -> p (happens to get the same address) Thread A: is_alloc(p) -> true Thread A: free(p) thinking it's not a double free because is_alloc returned true This scenario is possible because if it wasn't, you wouldn't need is_alloc in the first place. You only "need" it if you've lost track of your memory and have no clue what is allocated and what isn't and you're trying to solve the problem (the wrong way) with these runtime checks. > I think you misunderstand. You could have a (contrived) structure like: [...] > Rather than free each of these allocations individually, you would instead have `free_all(data)` (might not be a great name). At compile time the compiler would look at the structure and expand out to be all the free operations as required. Of course you would need the `is_alloc` to test if somebody actually did allocate memory. If you're going to change the language anyway (changing what the compiler does), just use C++ with unique_ptrs and they do precisely that without is_alloc. If pointer cycles are a concern (since we're only doing this to avoid proper pointer hygiene in the first place), you could allocate everything within `s` from a private arena and just free the arena.
- bArray 4y ago> This doesn't work because you don't know who allocated that memory. I obviously haven't fully fleshed it out (I'm not writing an RFC here), but address re-use would be a consideration as you mention. > You only "need" it if you've lost track of your memory and have no clue what is allocated and what isn't and you're trying to solve the problem (the wrong way) with these runtime checks. No, you can do: char* a = (char*)malloc(/**/); if(a == NULL) printf("error"); // Never runs /* Any other checks you want to perform */ /* Some processing later */ a[0] = 'a'; // Crash here In this case you have done nothing wrong. At the time of requesting memory there was enough space and the kernel said that you could have it. It's only when you come to actually access it did you find that it wasn't really allocated yet and there was no longer enough memory there for it. > If you're going to change the language anyway (changing what the compiler does), just use C++ with unique_ptrs and they do precisely that without is_alloc. You don't have to change the way in which the compiler works. You can likely do this with some macros. You would need some way to probe memory allocations though.
- mike_hock 4y ago> I obviously haven't fully fleshed it out (I'm not writing an RFC here) Whatever you don't state explicitly is assumed to be like the status quo. You've completely moved the goalposts with each reply. > No, you can do [...] Which a simple is_alloc doesn't help with because the allocator doesn't know if the kernel has actually mapped the memory to a physical page. This requires help from the kernel, which wasn't stated anywhere, nor was this goal stated anywhere. > You don't have to change the way in which the compiler works. You can likely do this with some macros. You can't reflect over a struct in C with macros. You can maybe build something that works with some macro hacks that require you to declare each auto-cleaned field with a special macro. This again is completely different from your previously stated idea that you just declare a struct with raw pointers and the compiler generates the appropriate free() calls.