![]() | This is an archive of past discussions about C dynamic memory allocation. Do not edit the contents of this page. If you wish to start a new discussion or revive an old one, please do so on the current talk page. |
Archive 1 | Archive 2 |
In all actuality, I've solved the heap problem for glibc on Linux, in theory; but I can't bring myself to write a "Hybrid allocator" section with an explaination. I'm currently trying to get the glibc people to adopt the design and code it, but they haven't responded to me yet.
The reason why I won't write the section is because I'm a source of bias. Until I get the thing accepted, my only reasoning for putting it on there could be that I'm trying to draw attention to the idea; however, it may be useful to draw attention to it, as others may benefit from the concept. So, if anyone wants me to write a section on it, I will, by request only.
requests+++
Pointers and arrays are not the same in C; malloc returns a pointer to an allocated region of memory, it does not return an array (or a pointer to the beginning of an array, or anything else). The article confused this in a few places. See here and here for more information. Neilc 18:12, 27 Mar 2005 (UTC)
/* File 1 */ #include <stdio.h> extern char *declared_as_ptr; int main(void) { printf("ptr = %s\n", declared_as_ptr); return 0; } /* File 2 */ char declared_as_ptr[] = "xxx";
A terminating zero is unnecessary if you know the string length -- in the case of the example, 11.
Although I agree that the discussion is irrelevent to this article, just as a point of interest it is true that most sources now discourage from casting the result of malloc, and from casting void * in general. Doing so is a hang over from Ye Olden Days which is now unnecessary, doesn't serve any good purpose, and can conceal compiler warnings. NicM 20:14, 19 March 2006 (UTC).
void *
is unnecessary, but I'm not sure there's a consensus on whether it is good style, and I definitely don't think that it is "strongly discouraged". It can actually produce some useful compiler warnings; for example:T *foo = malloc(sizeof T);
If we change the type of foo
but don't update the call to malloc
, the code will be buggy. One way to fix this is to use malloc(sizeof *foo)
, although I know a lot of people who find that construct unintuitive. Another way is to use an explicit cast:
T *foo = (T *) malloc(sizeof T);
which ensures that the programmer needs to update the RHS of the assignment if the type of the LHS changes. Now, I can't say I personally find this all that convincing (I would use sizeof *var
myself), but that's the argument I've heard for casting away from void pointers in the Postgres source, for example. Neilc
Time for me to "be bold" and make edits according to this discussion. Reinderientalk/contribs 00:02, 3 October 2010 (UTC)
I admit my experience with anything other than Windows is relatively slim so far, but I thought the term was mAlloc. Wrong?
Liastnir 03:37, 10 April 2006 (UTC)
'alloca', commonly available even if not standardised by the C standard, has allowed it for a long time, and C99 specifies that automatic(on-stack) arrays may have their lengths specified by an expression computed at runtime (although actual support for this is relatively low; GCC's support for this is "broken"). So only the lifetime management issue (or a need/desire for extreme portability) is(are) what makes malloc(heap-allocation, that is) necessary in C. Also, recursive function calls can even be used to effectively create a stack-based variable-size linked list, portably. Dynamic amounts of stack memory completely make sense. Of course, historical reasons play a part in what is used the most today, and quite possibly in the original historical reasons for malloc (I don't myself know). I'm not sure how I'd rework the rationale section though, but anyone may feel free to do it (of course!) if they have any idea how to go about it (or are simply feeling more motivated at the moment...). —Isaac Dupree(talk) 22:29, 24 June 2006 (UTC)
The GCC support for variable length arrays is broken? I've been using it. Also, I heard that GCC supported it even before C99. Maybe C99 has an additional requiremente that GCC does not fulfill yet. Does anybody know? Jorge Peixoto
The webpage Variable Length - Using the GNU Compiler Collection (GCC), which I have just found by googling this search terms, supports my idea that GCC supports variable length arrays quite well, but not exactly like C99 demands. Jorge Peixoto 22:52, 20 February 2007 (UTC)
Oh, I have just realized that variable length arrays are supported in GCC by default: one doesn't have to flip a switch like -std=gnu99 or whatever. They wouldn't enable it by default if it was really broken. Jorge Peixoto 23:00, 20 February 2007 (UTC)
I'm working on the Steel Memory Allocator, a design I came up with based on everything in the universe just about. The page for it is:
http://steel-malloc.sourceforge.net/
Is this worth adding to 'External links'? I'm basically documenting the entire design of my allocator before I start (site due to be finished 2006 Sep 15) so there's a lot of interesting information; although it's not really much relevant to anything. ;)
At least whoever writes Steel Memory Allocator once it's done will have a lot to go on, since I can't write it myself. —Preceding unsigned comment added by Bluefoxicy (talk • contribs) 05:38, 14 September 2006
A new user, User:Davedice contribs, added a link to an article that was apparently created by him. Here is the link:
Could some folks look at this article and decide if this is link is appropriate? Since I'm the person who reverted it, I would prefer not to decide on my own. wrp103 (Bill Pringle) 23:56, 26 February 2007 (UTC)
Not sure if the page is about ANSI C only. But perhaps memory alignment should be mentioned, and functions like memalign(), valloc(), and such? —The preceding unsigned comment was added by Jwagnerhki (talk • contribs) 20:40, 3 March 2007 (UTC).
free(NULL) is undefined, not safe. —Preceding unsigned comment added by 89.132.149.210 (talk) 08:38, 17 June 2008 (UTC)
Comment moved from my talk page in response to this edit of mine:
I have now checked the C99 standard, and indeed it says in section 7.20.3.3:
and likewise for calloc and realloc. On the basis of this, I have reverted the above edit.
As referenced in the above comment, the C99 standard differentiates between a "null pointer" and "null pointer constant" (6.3.2.3) as follows:
void *
, is called a null pointer constant. If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function."and it states that the macro NULL
is defined as a null pointer constant.
Yet despite this, manual pages (e.g. for glibc) typically state that malloc "returns NULL" rather than "returns a null pointer". This was the basis for my earlier edit. On thinking about it, it seems that the ambiguity is resolved as follows -- please comment if you have anything to add to it.
The implentation of NULL may be as (void *) 0
but according to the standard it may instead be an integer type with value 0. In all cases NULL is a null pointer constant, but if NULL is defined as a void *
, rather than (say) int
, then it will also happen to be a null pointer. In Linux glibc, NULL is implemented as follows (in <linux/stddef.h>
):
#if defined(__cplusplus) #define NULL 0 #else #define NULL ((void *)0) #endif
So (in the case of plain C), NULL is in fact a (void *) 0
. Given that the return value of a failed malloc call is a null pointer of type void *
, hence equal to (void *) 0
, it is fair for the manpage here to say that malloc "returns NULL", although this is a less general statement. (That said, despite this distinction, in most practical cases you will test for a null pointer returned by comparing it with NULL.) — Alan✉ 12:59, 1 October 2008 (UTC)
sizeof(size_t)−1 is not same as SIZE_MAX sizeof(size_t) returns size of data type (usualy unsigned int = 4B) not maximum value that can hold variable of that type —Preceding unsigned comment added by 213.220.206.78 (talk) 10:44, 26 December 2008 (UTC)
"sizeof(size_t)−1" is wrong, it will give "3", not "0xFFFFFFFF" on IA-32. —Preceding unsigned comment added by 92.113.180.34 (talk) 02:41, 2 January 2009 (UTC)
it's based on: libg++-1.2X malloc -> dlmalloc-2.7.0 -> ptmalloc2-20011215 -> glibc-malloc-2.3 —Preceding unsigned comment added by Xose.vazquez (talk • contribs) 22:29, 7 May 2009 (UTC)
In the section of this page, Use after free, it is claimed that after a pointer has been passed to free, that:
Even attempting to print the variable with printf is undefined behavior (assuming malloc did not return a null pointer); for example:
printf("%p", (void *) ptr); /* Undefined behavior */
Is the behavior really undefined? Assuming that we discount that the value of the pointer we get back from malloc is undefined, the call to free() is pass by value. The value of ptr will not change as a result of passing it to free. The printf() should print the value of the pointer as it was before the call to free (ie. this is the defined behavior).
The only doubt to this is that, perhaps the original poster was focusing on the %p format placeholder. The wikipedia article on printf states that the placeholder specifies:
Print a void * (pointer to void) in an implementation-defined format.
This specification is a little generic (implementation-defined format). If an implementation were to attempt to "pretty-print" the value pointed to by ptr, then the assertion of undefined behavior would be reasonable.
I suggest that this is not what is meant by "implementation-defined format", and that the scope is restricted to an arbitrary formatting of the value of the pointer itself (not de-referenced). Even if my suggestion is wrong, I assert that in this example, it is only the use of the %p placeholder which presents the problem. So the claim that
Even attempting to print the variable with printf is undefined behavior (assuming malloc did not return a null pointer);
is not correct, because other forms of printf would be defined to print the value of the pointer as it was before the call to free. Example:
printf("%x", ptr); /* Hex value of ptr */
148.182.52.148 (talk) 04:28, 27 October 2009 (UTC)
The problem with switching to the linked list example is that it will no longer illustrate the same point. Section 6.2.4 of the C standard (Storage durations of objects) says explicitly that reference to an object outside of its lifetime is undefined behaviour. There is no question that any access through a freed pointer is undefined; the question is whether use of the pointer itself is undefined behaviour. I think that it is undefined, but the argument is not a simple one.
The same section says that a pointer to an object becomes indeterminate when the object's lifetime ends. An indeterminate value is a technical term defined in 3.17.12. It is either a valid value of the type in question or it is a trap representation. It is perfectly true that the free function can't alter the value of the pointer it is passed, but it can alter the meaning of that pointer in such a way that it becomes a trap representation. For example, on some exotic hardware the free function might alter some hardware registers so that any reference to the pointer at all would result in a trap.
The standard states that this is undefined behaviour explicitly in two places, but neither is in normative text. One is 6.5.2.5 example 17and the other is Appendix J which lists undefined behaviour. Both of these state that use (not just use in indirection) of an indeterminate pointer is undefined behaviour.
I would suggest that the current example be kept. Ben Bacarisse (talk) 23:37, 6 February 2010 (UTC)
This section needs attention. "The best threaded malloc ever" is non-encyclopedic. I don't know much about it, so I'll leave this task to someone else. —Preceding unsigned comment added by Jdstroy (talk • contribs) 05:35, 7 February 2010 (UTC)
nedmalloc is stated as "essentially dlmalloc wrapped by a per-thread lookaside cache to improve execution concurrency", which is unfortunate since this particular software is a rather bad example and the claim "to improve execution concurrency" is a false claim. The claim on the project's website "more than 125 times faster than the standard Win32 memory allocator" is just ridiculous. The author of that software needs to do a reality check.
I have just benchmarked the latest unstable version (the stable one would not even build). The results are identical to the results I had about a year ago with an older version.
Benchmarks were performed using MinGW gcc 4.4 and 4.5 under Windows XP 32 bit on a Core2 quad, with every possible compiler optimization enabled and tuned for the architecture. For being able to build the unstable version with MinGW (producing a good number of warnings), one has to manually add a few #defines. Also, the standard and low-frag heap allocator benchmarks are disabled by default.
The benchmark is more than disillusioning, even more so as the benchmark program is very much contrieved to test specifically the advantageous case (many allocations/deallocations with ultra-high contention and a relatively small total set) which nedalloc was built for, and neither the standard, nor the low-frag allocator are specifically tuned for Core2.
With one thread, both the standard allocator and the low-frag allocator outperform nedalloc by 25-35%. With 2 concurrent threads, the standard allocator is beginnign to spend a considerable amount of system time spinning, but is still about 10% faster than nedalloc. With 4 concurrent threads, nedalloc beats the standard allocator, but is still about 16-18% slower than the low-frag allocator. With 8 concurrent threads (on a 4-core no-HT machine), the standard allocator has deteriorated at about 50% of its single-threaded performance (which is surprisingly good for a generic locking implementation!), while nedalloc is again able to gain a little, but the low-frag allocator still outperforms nedalloc by 11%. —Preceding unsigned comment added by 92.202.27.95 (talk) 14:40, 28 July 2010 (UTC)