why memory for primitive data types is not allocated? [duplicate] - objective-c

This question already has answers here:
What and where are the stack and heap?
(31 answers)
Closed 8 years ago.
Primitive data types such as char, bool and int have some memory. Suppose char, which has 1 byte of memory. When we use a char variable in our code, then the variable must require 1 byte of memory. Why don't we allocate memory in this case. And as we never allocate memory for it, how does it use the memory ,i.e. Is the CPU allocate memory for it in this case.Also I read somewhere that the primitive data types are put on stack and removed when the work is done for it. What kind of stack? How does the stack comes into picture in this case?

When we create an NSString * variable, we don't allocate the memory for this either.
We only allocate memory when alloc is called, either directly by us or inside a method we call.
An NSString object exists on the heap in memory we've allocated, but the NSString * variable (which is, a pointer to an NSString object) exists in memory on the stack which we do not allocate.
For example, given these two variables:
NSString *stringOne;
NSString *stringTwo;
So far, neither has been allocated any memory on the heap, although they do exist in memory in the exact same way a char, BOOL, or int exists in memory.
NSString *stringOne = [[NSString alloc] initWithString:#"Hello world"];
NSString *stringTwo = stringOne;
Now what has happened? We allocated some memory on the heap for an NSString object. We then initialized this memory to represent the string "Hello world" and then returned a pointer to this object and assigned it to stringOne.
Next, we simply copied that pointer over into the stack memory we're using for stringTwo. We didn't allocate any extra memory on the heap. We simply made our two string variable point to the same allocated memory on the heap.
The question and answer jsd linked in the comments has more explanation on stack and heap memory which will answer some of your questions.
It's also worth noting that a lot of other programming languages such as C++ allow objects to be created on the stack, in which case we don't allocate them, as we would with heap objects. They do exist in memory, just more similarly to primitive data types.

At the risk of being over simplistic, there are three classes of memory for data: 1) static, 2) stack 3) heap.
They are allocated in different ways.
if you have
static char something ;
defined in a function or
char something ;
outside of a function, that data is defined by the linker using instructions from the compiler and allocated by the program loaders.
Nearly every processor in existence uses a stack to support nested data (e.g., function calls). The stack is a block of memory that exists for every process (and for every processor mode). There is a a hardware register called the Stack Pointer that identifies the current position of the stack. Usually the SP starts at the high end of the stack and works downward. To allocate memory on the stack, the program subtracts the number of bytes required from the stack pointer. To deallocate, it adds to the stack pointer. The allocations and deallocations always take place at the same end.
There are then two operations on the stack. PUSH means put something on the stack. POP removes it. Most processors have instructions to PUSH and POP
If you have
char something
defined within a function, that memory is allocated by the program as directed by the compiler by doing something like this to adjust the stack pointer (I'm leaving out a frame pointer for now)
SUB BYTESNEEDED, SP
upon entering the function and freed by doing
ADD BYTESNEEDED, SP
before leaving the function. During the execution of the function, the local variables are at offsets from the stack pointer.
This usually done by using a second register, usually called a frame pointer. A function usually does something like this at the start
PUSH FP ; Save the old Frame Point
MOV SP FP ; Save the stack pointer
SUB BYTESNEEDED, SP
at the end the function does something like
MOV FP, SP ; Free all the stack allocated by the function
POP FP ; Restore the old stack pointer
The reason for using two registers is that it is possible to dynamically allocate data from the stack.
THere is a common function (although I believe it is not a standard C function) called alloca that is an alternative to malloc that allocates from the stack
void dosomething (int amount)
{
char *data = alloca (amount) ;
}
With alloca, the data is automatically freed when the function returns and resets the stack.
That is a long winded answer to your question. Yes, when declare a char, there has to be an allocation for it. However, this allocation is done behind the scenes without effort on your part.

Related

How to release a struct that was passed by reference to c code and its member was malloc'ed there?

I'm getting "malloc: * error for object 0xbfffe160: pointer being freed was not allocated" when trying to free memory (in objective-c code) of an object that was allocated inside c function. This C function creates and returns binary data packet that is used as NSData later. Here's my obj-c code part where I'm creating struct variable and passing it by reference to C function:
MyPacket packetRef;
allocAuthentificationCodePacket(&packetRef);
NSData *data = [NSData dataWithBytes:packetRef.bytes length:packetRef.packet->packetSize];
free(&packetRef); // getting error
Everything work fine, except I'm trying to release the memory because the data should be retained by NSData variable. The C functions performs calloc inside itself, so I should somehow to release that memory:
packetRef->bytes = calloc(1, sizeof(*packetRef));
Here's are my structs for storing binary data:
typedef struct {
uint8_t packetType;
uint16_t packetBody;
} MyStruct;
and another struct:
typedef union {
const uint8_t *bytes;
MyStruct *packet;
} MyPacket;
How should I free the memory? The error I'm getting is not crash, it just a message in debug console when running unit tests.
UPDATE. Tried to release "bytes" struct member but getting the same error message:
free(&packetRef.bytes);
UPDATE2. Thanks, the suggested way did worked and malloc error message disappeared from console:
free(packetRef.bytes);
However, getting a warning in Xcode "Passing 'const uint8_t *' (aka 'const unsigned char *') to parameter of type 'void *' discards qualifiers". I'm using Apple LLVM 4.1 compiler. C function resides in separate file and only a header is included because Android guys will have to reuse it.
UPDATE3. Thanks to #simonc and #nos who have pointed out the struct member "bytes" has const. The warning has disappeared after removing const. The initial idea of using const was to protect "bytes" from modification.
This is always wrong. (Hint: It's almost always wrong to put & inside of free().)
MyPacket packetRef;
...
free(&packetRef); // getting error
It doesn't matter what MyPacket is -- it has automatic storage duration, i.e., the compiler automatically allocates storage and frees it when the function exits.
Do not free() something unless it came from malloc() (or calloc(), etc.)
Since packetRef.bytes was allocated with calloc(), you can free() that instead.
MyPacket packetRef;
allocAuthentificationCodePacket(&packetRef);
...
free(packetRef.bytes);
Update
If the function that you call, allocAuthentificationCodePacket, contains the code:
packetRef->bytes = calloc(1, sizeof(*packetRef));
And if the bytes field has type const uint8_t *, then something is wrong.
Perhaps your code is wrong, and you are supposed to call some function to free the packet rather than freeing it yourself.
Perhaps the type of the bytes field is wrong, and should be uint8_t * instead of const uint8_t *.
Perhaps allocAuthentificationCodePacket is wrong.
Who knows? It's not wrong enough to crash, but it is a problem.
Footnote
There are no references in C. &x is "address of x", not "reference to x".
Let's consider the following code:
char *x = malloc(10);
free(x);
When people talk about this code, they will say something like "x is allocated on the heap", but that's not technically correct, x is allocated on the stack and contains the address of 10 bytes on the heap. Likewise, the line free(x) does not actually free x, it frees the memory which x points to.
So when someone tells you, "don't forget to free x", you know they actually mean "don't forget to free the memory which the value contained in x points to". People are sloppy with terminology but computers aren't.
packetRef is a stack variable in your example with packetRef->bytes heap allocated. You should therefore call free(packetRef.bytes)
Since you allocate the memory inside a function - allocAuthentificationCodePacket - you may want to create another function to free the memory
void freePacket(MyPacket* packet)
{
free(packet->bytes);
}

Dereference 2D Array Pointer In C

I am pointing to the address of a 2D array, and I am confused as to how to dereference the pointer to free up the memory again. (I don't use "->" or "*". Is that wrong?)
My code:
double array[12][12];
//filled with numbers
double *arrayPtr; //pointer
arrayPtr = &array[0][0]; //pointing to address
multiply(arrayPtr, arrayPtr); //this works fine
//Do I need to do anything further to make sure my memory management is correct? And if so, why?
In this case, the answer is no -- since you simply defined array (didn't use something like malloc to allocate it) you don't have to do anything to free it either. If it was local (defined inside a function) it'll be freed automatically when you exit the function. If you defined it outside any function, it's a global, so it'll exist the entire time the program runs. Either way, you don't have to d any explicit memory management.
double array[12][12];
You're declaring array on the stack. It's not dynamically allocated with the heap, so you don't "free up the memory".
double *arrayPtr; //pointer
arrayPtr = &array[0][0]; //pointing to address
If you want to point to the first element, this would suffice:
double* arrayPtr = array;
First, there a quite different between C and C++
In C to use memory management you shall use malloc/calloc/realloc and free. In c++ you will use new and delete.
In your code.
double array[12][12];
This is imply to allocate memory in stack. So the memory will be allocated to the scope of this program section so that it will be green when the scope of this variable end.
If you will to use free you will need
double **array;
array = (double **) malloc(sizeof(double*));
*array = (double*) malloc (24 * sizeof(double));
free (*array);
free (array);

Free vs. encapsulation

In programming there is a general rule introduced by Kernighan & Ritchie saying that you have call a "free" for all space allocated by a "malloc".
So the following code is correct:
- (UIImage*) convertImage:(UIImage*)sourceImage {
unsigned char *rawData = malloc(requiredSpace);
...
...
free(rawData);
return imageRef;
}
However you also have encapsulation within a function. So after the return from the function, the memory will be automatically freed. So theoretically the free is not absolutely required in the above example. Is this correct?
Absolutely no.
The free is necessary since the memory will be freed only for statically allocated variables. If you use malloc (as well as calloc or realloc) you are dynamically allocating memory that will not be freed except if you explicitly call free.
For example:
-(void)method {
char a[10];
char *b = (char*) malloc(10*sizeof(char));
}
a will be destroyed at the end of the scope (at least, will be marked as free memory, so that you cannot rely anymore on its content), while b remains in memory until the end of the program. If you lose the pointer to that memory address (maybe assigning another value to b or simply ending the function without returning b), you will not be able to free the memory anymore, and this will bring to a memory leak.

Returning a C-array and memory management

I am slightly bemused by the following property points of class MKMultiPoint in MapKit:
#property (nonatomic, readonly) MKMapPoint *points
It returns an array of struct. One can know the number of elements in the array with the pointCount property.
With my limited knowledge of C, I always thought C-arrays could only be "sort of returned" if passed by reference to a function because the caller is responsible for allocating the memory and then releasing it.
If I were to write a similar property, who would allocate the memory for the array (presumably the callee) and more importantly who would free it (presumably the caller)? That sounds a bit risky to me. Besides, the documentation for the property above doesn't say anything about having to free memory.
What am I missing?
(The sample code is in C).
The good practice is to allocate and free a resource at the same level. There are two ways to define a function that returns an array of things:
// `points` are allocated and freed by the caller.
void MakePoints (MKMapPoint *points, size_t number_of_points);
// usage:
size_t count = 10;
MKMapPoint *points = malloc (sizeof (MKMapPoint) * 10);
MakePoints (points, count);
// Use points
free (points);
// or simply
MKMapPoint points[10];
MakePoints (points, 10);
// Use points
The second way is to let the library function manage the memory:
MKMapPoint *MakePoints (size_t number_of_points);
void FreePoints (MKMapPoint *points);
// Usage:
MKMapPoint *points = MakePoints (10);
// Use points
// The library need not necessarily call free() on points,
// it might reuse it in further calls to MakePoints().
FreePoints (points);
The receiver, in most cases, would handle allocating the memory. Who frees it depends on how you determine ownership. Is the memory allocated by the receiver no longer needed once it's returned? If so, you should probably note in your documentation that the caller needs to free the returned array. If the receiver can reuse the returned memory, leave deallocation to it.
If you wanted to leave it up to the callee to handle memory allocation, you probably wouldn't use a property and instead opt for a message and property like so:
- (NSUInteger) mapPointCount;
- (void) getMapPoints:(MKMapPoint *)pointsOut;
where the sender should provide an existing buffer to store obj.mapPointCount number of MKMapPoints in. Then, you've placed the responsibility for allocation/deallocation on the caller.
If you don't want to go that route, and since the memory in question can't be retained/released/autoreleased by the receiver, I would leave it up to the caller to release it. If you want to make it somewhat clear that the memory is not to be freed, return it with the type const MKMapPoint * and note it in some form of documentation (which should hopefully make it clear that the memory is not owned by whoever accesses the data).
Alternatively, store it in an NSData or something and make it clear that once the next autorelease pool is drained, the pointer is invalid. However, that's a little less friendly, and possibly not safe with garbage collection. Probably wrong about that last bit, but I don't know enough to say, so I'll prefer caution for now.

Asterisk usage in Objective-C: related questions

I had a couple questions related to this: Asterisk usage in Objective-C
NSArray array; in a local scope would be an object "allocated" on the stack. NSArray *array; indicates an object backed by a hunk of memory, typically allocated from the heap.
How do you know when something is allocated on the stack and on the heap? Are all local variables on the stack and are all pointers on the heap?
Because you aren't dereferencing the pointer to the object and that pointer to the object is critical within the method implementation itself. When you say...
Huh
How do you know when something is allocated on the stack and on the heap? Are all local variables on the stack …
It doesn't matter. The stack and heap are implementation details; the C and Objective-C languages do not know about them, and you should generally not have any reason to care whether something is on the stack or the heap.
On Mac OS X, local variables are on the stack. But, for almost all purposes, this is of no consequence. Don't worry about it.
… and are all pointers on the heap?
No. Pointers are memory addresses; that's all.
Pointer variables can be anywhere any other variables can, which is to say, anywhere (subject to implementation-defined limitations that you needn't care about, as noted above).
See my pointer tutorial for more information.
Because you aren't dereferencing the pointer to the object and that pointer to the object is critical within the method implementation itself. When you say...
Huh
A pointer is a memory address. As such, it refers to the memory at that address. Dereferencing the pointer is accessing that memory.
You never, ever directly access the memory a Cocoa object takes up. You only send it messages, to either ask it questions or tell it to do things. Thus, you never dereference the pointer.
“…that pointer to the object is critical within the method implementation itself.” means that the object, in its method implementations, will need its own pointer. It's only possible to send a message to a pointer to an object (this detail is usually elided). If you somehow pulled this off, the receiver of the message (that is, the object you messaged) would not have its own pointer.
Suppose it were possible to send a message to a dereferenced object. The norm is still to send messages to pointers to objects, so in all likelihood, the object will still need that pointer to itself—making that hypothetical ability to message a dereferenced object useless.
Since it's useless, they left it out entirely. The object will need its own pointer (the pointer is critical to the object's method implementations), so you can only send a message to its pointer.
The * is the dereference operator for C, C++ and Objective-C. Understanding the dereference operator, and memory management in general is far broader than Objective-C. This is a fundamental skill for any C/C++/Objective-C developer. Have a look at the multitude of intro C tutorials on the net to learn more.
Edit: any tutorial on c pointers will do. Such as this http://home.netcom.com/~tjensen/ptr/pointers.htm
In Cocoa, you'll never use stack allocated objects; ALL objects will be prefaced with a * (remember that the type "id"is really another word for "pointer to SOME object") and created on the heap.
You'll always have this:
NSArray *myArray;
and never this:
NSArray myArray;
You can ignore the second chunk, since you're always dereferencing the pointer.
Hope these naive toy examples can help you.
In C, in a function,
int x; // x is a variable of type int in stack
int *xp; // xp is a variable of type int * (pointer to int) in stack
int *xp2 = (int *) malloc(sizeof(int)); // xp2 is a variable in stack, it points to a memory location(size is of int) in heap
xp = &x; // xp can point to x
xp = xp2; // xp can also point to what xp2 points to
free(xp2); // now xp and xp2 point to a freed memory, BAD to use xp and xp2 now.
int **y; // y is a variable in stack, type is int **
y = (int **) malloc(sizeof(int *)); // allocate a piece of memory in heap, to hold a pointer to int(int *)
*y = (int *) malloc(sizeof(int)); // allocate a piece of memory in heap, to hold an int
**y = 100; // now we can use it
free(*y);
free(y);
In C++, in a function or member function(method),
SomeClass a1; // a1 is an object of type SomeClass in stack
SomeClass *a2 = new SomeClass(); // a2 is a pointer(in stack) pointing to an object(of type SomeClass) located in heap
delete a2;
So in C++, objects can exist in stack or heap
In Java, in a function or method,
SomeClass b1; // b1 is just a reference, no object exists yet
b1 = new SomeClass(); // in java, objects can only exist in heap
int x; // however, primitive types are in stack,
In Objective-C, in a function or method,
SomeClass c1; // you can't do this.
SomeClass *c2 = [[SomeClass alloca] init]; // c1 is a pointer in stack, pointing to an object in heap
[c2 release];