Implementations of malloc can vary, but conceptually, the heap consists of blocks of memory that are in use and blocks of memory that are free, each with varying sizes. When malloc(n) is called, the malloc implementation will attempt to search for a free block of size greater than or equal to n, plus any meta data it needs to store in the block if that is the scheme it uses. I've seen a malloc implementation that doesn't store any meta data with allocated blocks, and instead, keeps that information as compactly as possible. This way, traversing the data structure when looking for a free block wont cause so many pages to be loaded in memory when they may have been paged out to disk. I don't know how popular this technique is. I just saw it in a paper once.
putting \0's in the malloced space after calling free on it would invoke unneeded work in functioning programs, but doing that would make memory errors a little bit less severe and easier to track in a few cases. But all and all, it wouldn't be that useful.
Name:
Anonymous2012-01-13 11:01
This is the simplest conforming malloc implementation that doesn't just return NULL. #include <string.h>
#ifndef NULL
#define NULL ((void *)0)
#endif
#define SOME_BIG_NUMBER (1024*1024*1024)
static char malloc_space[SOME_BIG_NUMBER];
void *malloc(size_t n) {
static char *p = malloc_space;
char *q = p;
if (p+n > &malloc_space[SOME_BIG_NUMBER]) return NULL;
p += n;
return q;
}
void *calloc(size_t nelem, size_t elsize) {
/* uninitialized static variables are zero */
return malloc(nelem*elsize);
}
>>11
- input parameter n unused
- unmatched parenthesis after if test
- doesn't conform to calloc() as it is supposed to return a cleared memory block of size n*s
Name:
YOUR_SUPER_NIGGER2012-01-13 11:34
>>12
It should be unsigned, but the toilet scrubbing monkey who provided the code template had the args as size_t. Ya know, everyone can't be as cool as me.
>>12
Presumably the unused was because I had n=s instead n*s. The latter being the correct way. Anyways, this should should shut up size. The effect is the same as when I slap up your fat wife.
/*Begin the rogaine and viagra session*/
void *calloc(size_t n, size_t s) {
size_t i, nb;
char *p, *q;
nb = n*s;
if ((p = q = malloc(nb) != NULL)
for (i = 0; i < nb; i++)
*p++ = 0;
return q;
}
Name:
Anonymous2012-01-13 12:01
>>16
Since standard string.h defines NULL, if NULL is not defined, then the string.h is non-standard. In that case it may be a pre-standard compiler that doesn't even have memmove() (maybe it has bcopy() instead). As an analogy, since standard C defines __STDC__, if __STDC__ is not defined, then the implementation is non-standard. Anyway, malloc, realloc, calloc, and free are already reserved identifiers, but in a free-standing implementation (e.g. MS-DOS, a kernel, or an embedded system) they are not required.
#ifndef __STDC__
import java.io.*;
class Hello
{
public static void main(String args[])
{
System.out.println("Hello, world!");
}
}
#else
#include <stdio.h>
int main(void) {
printf("Hello, world!\n");
}
#endif
This program is strictly conforming C. If __STDC__ isn't defined, it could be a preprocessor for Java or GNU Assembler for all we know.
"3. An integer constant expesion with value 0, or such an expression cast to type 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."
The second <string.h> is included NULL becomes a reserved identifier.
Name:
Anonymous2012-01-13 12:50
>>13
If you can't be sure that string.h defines NULL how are you sure that it defines size_t, or that it declares any of the functions?
Name:
Anonymous2012-01-13 12:54
>>22
This is your daily reminder that the statement every subset of a countable set is also countable is an absolutely true statement that never fails under any conditions.
Keep denying the truth you mental midget, I'm sure it'll change some day. Oh wait...
>>25
You can't be sure. But the #ifndef means that on a conforming implementation, the #define has no effect. It merely checks for the existence of the identifier. On a non-conforming implementation, however, #include itself could do anything, or the preprocessor may not even exist. And yes, if a string.h doesn't have NULL, it may not have size_t either, and the functions it does have could be missing, broken or defined to remove() every file on the system. Either way, that doesn't make that code non-conforming, it just makes it superfluous. #ifdef THIS_IS_A_UNIX_SYSTEM
#include <unistd.h>
#endif
#ifdef THIS_IS_A_WINDOWS_SYSTEM
#include <windows.h>
#endif
#ifdef __STDC_HOSTED__
#include <stdio.h>
#endif
#ifndef NULL
/* if NULL was previously defined, this will do nothing */
#define NULL ((void *)0)
#endif
This is also conforming C89/C99/C11 code. That's how conditional compilation works.
Name:
Anonymous2012-01-13 15:34
Not sure why the bickering about preprocessor identifiers
when you have a static char array.
``static char malloc_space[SOME_BIG_NUMBER];''
As scientifically proven by the ##C snippet,
you might not even portably cast around pointers to
static arrays of different sizes, nevermind using one
to simulate malloc:
<kate`> Draconx|Laptop, do you know if it's well-defined to point an int (*)[5][7] at the first element of an int [35], and dereference it, please?
<Draconx|Laptop> kate`, I've never really been sure about that kind of thing.
<kate`> i think (and hope) it is well-defined and legal
<Draconx|Laptop> kate`, the C1x drafts have a lot more detail about alignment and such, so you might want to check them out to see if it's specified.
<Zhivago> kate: The only question would be alignment requirements.
<kate`> Draconx|Laptop, well, i'm willing to trust that it's ok, rather than read C1x :)
<kate`> Zhivago, i don't see how they could be permitted to differ
<Zhivago> kate: If that address is universally aligned, then it must be valid.
<Zhivago> kate: I see nothing that constrains an array not to have tighter alignment requirements than its elements.
<Zhivago> kate: And it is possible that an abi might constrain this in various ways.
<Zhivago> kate: I agree that it would be an outre system that had such.
<kate`> Zhivago, but how could that differ from the pointer to an array of arrays of the same type? surely the alignment would be the same?
<Zhivago> kate: What same type?
<kate`> Zhivago, the element type - int, in my case
<Zhivago> kate: You have an array of int and you have an array of int[x]
<kate`> and the alignment for those two needn't be the same?
<Zhivago> kate: I can think of nothing that requires that, no.
<kate`> i see, ok
<Zhivago> kate: The alignment is constrained to at least that satisfying int's requirement.
<kate`> so is this also true for an array of int [5] versus an array of int [7]?
<kate`> (namely a pointer to either)
<Zhivago> kate: It is also constrained such that the end of the array must be correctly aligned for another such array.
<Zhivago> bbiab
<kate`> hey... :p
<Zhivago> kate: Anyhow, I have great difficulty imagining such an architecture, but a sufficiently perverse person -- such as yourself -- could probably manage it.
<Zhivago> kate: I have revised my programming language syntax. Now "Doesn't require fish.
>>27
No it's not conforming you stupid piece of shit, NULL becomes a reserved identifier the second string.h is included, it doesn't matter if you check if it's defined or not, attempting to define it is non-conformant code since you're using a reserved identifier. Read any of the fucking standards you mentioned in your post you fucking retard.
>>35 Read any of the fucking standards you mentioned in your post you fucking retard. C99 6.10-4 When in a group that is skipped (6.10.1), the directive syntax is relaxed to allow any sequence of preprocessing tokens to occur between the directive name and the following new-line character.
Let me break this down.
1. string.h defines NULL.
2. The directive is #ifndef NULL.
3. If string.h is included, the condition is false.
4. A group is "skipped" if the condition in a conditional preprocessing directive is false.
5. All directives (lines beginning with # followed by a valid directive name, such as #define) in the group are skipped, no matter what tokens follow them on the line.
6. The #define is skipped, no matter what else the line contains.
#include <string.h>
#ifndef NULL /* on a conforming implementation, this will always be skipped */
#define NULL "you stupid piece of shit" -- >>35
#define __LOOK_IM_USING_DOUBLE_UNDERSCORES__ When in a group that is skipped (6.10.1), the directive syntax is relaxed to allow any sequence of preprocessing tokens to occur between the directive name and the following new-line character.
#define __STDC__ "Read any of the fucking standards you mentioned in your post you fucking retard." -- >>35
#include "a file that doesn't exist.h"
#endif
This is conforming code. None of the directives have any effect. Otherwise the compiler would complain about missing files and redefined identifiers whenever someone used conditional compilation. Include guards and testing for the OS wouldn't work. Why do you think the C standard defines __STDC__ in the first place?
Name:
Anonymous2012-01-13 20:06
>>36
But you claimed that NULL might not be defined in which case it would define NULL to be ((void *) 0) and just because it isn't defined doesn't mean that it's not a reserved identifier when you include string.h you fucking retard.
>>38
It is after you include the header <string.h>, some headers have that as their singular purpose, like <stdbool.h> which makes bool a reserved identifier and <stdnoreturn.h> which makes noreturn a reserved identifier.
Besides all of this is ridiculous as the people in this thread seem to confuse NULL (which may be of type int) with a null pointer value.