How can I remove memory allocated by const char* arrayname in iOS 7.
here is my code
const char *bytes = [encodedString UTF8String];
Now I want to release bytes with ARC enabled. How can I do that.
You don't need to do anything to ensure it will be released eventually. Quoting the documentation:
The returned C string is a pointer to a structure inside the string object, which may have a lifetime shorter than the string object and will certainly not have a longer lifetime. Therefore, you should copy the C string if it needs to be stored outside of the memory context in which you called this method.
In other words, you don't know the lifetime of the array, but you know it may not live long and it will be freed automatically.
You should not release memory pointed by bytes pointer directly as it is managed by encodedString object. To free that memory get rid of all strong references to encodedString and memory should get released
Related
Is the const char* valid?
Does ARC keep track of the pointer returned by this function?
const char* getUrl()
{
// retrieve an url with obj-c
NSString *maybeTmp = [[NSString alloc] initWithString:#"some url"];
return [maybeTmp UTF8String];
}
This code is used as a bridge. A C library is going to call this function.
I would guess that ARC doesn't keep track of that pointer and will release this NSString once the function getUrl() returns, leaving the pointer as non valid.
Is the pointer non-valid after the end of the function?
If non-valid, is there a way to explicitly ask ARC to keep track of it?
No, ARC does not (and cannot) manage lifetimes of non-object types. If you take a look at the documentation for -[NSString UTF8String], you can also see the following:
This C string is a pointer to a structure inside the string object, which may have a lifetime shorter than the string object and will certainly not have a longer lifetime. Therefore, you should copy the C string if it needs to be stored outside of the memory context in which you use this property.
The UTF-8 string you get back has a maximum lifetime of the lifetime of the source NSString (which ARC will clean up at the end of the function), so if you need to hold on to the string, you'll need to make a copy using strdup or similar (and manage the lifetime yourself).
Is the pointer non-valid after the end of the function?
You are correct. ARC keeps track only of memory allocated to reference-counted objects. Sinc char* returned by UTF8String does not refer to a reference-counted object, ARC does not know of its existence.
If non-valid, is there a way to explicitly ask ARC to keep track of it?
No, because char* lacks "infrastructure" for keeping reference count. You could either return a reference-counted object which encloses your char*, or use malloc, make a copy, and let the caller free the string.
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);
}
cStringUsingEncoding: returns a "const char *" despite it is returning a dynamically allocated C string(from it's documentation). So, what is the purpose of const here? We could simply modify the returned C string by casting to char *.
cStringUsingEncoding:
The returned C string is guaranteed to be valid only until either the
receiver is freed, or until the current autorelease pool is emptied,
whichever occurs first.
I think library is following the common practice of pointer-to-const; it's not expected to be modified or released.
From Objective-C runtime;
const char * object_getClassName(id obj) -- Nothing specified about the returned string.
char * method_copyArgumentType(Method method, unsigned int index) -- You must free the string with free(). (May be it's advising because of it's returning a copy.)
The common pattern is that you should not modify buffers that you don't own. const documents and (somewhat) enforces this.
As for cStringUsingEncoding:, The documentation is saying that the returned buffer is only valid as long as the NSString from which you received it, or for the duration of the current autorelease pool. This implies that you do not own the returned buffer, because you're not expected to release it.
Your last two examples from the runtime follow the same convention:
const char * object_getClassName(id obj)
Doesn't inform you that you should release the buffer, and the name doesn't contain any indication that you own the buffer. Therefore you don't free() it, and you don't modify it.
char * method_copyArgumentType(Method method, unsigned int index)
The docs explicitly tell you that you should free the buffer, and the function name contains the tell-tale copy which also implies that you own the buffer. Therefore you can modify it all you want, and must free() it.
Thing is, the result is const because
modifying it will not change the string itself, and the cString is really just meant to be a different representation of the string
it will probably return the same cString "over and over again", as long as the string doesn't change.
Other than that, declaring a result to be const even if the implementation doesn't enforce or require that is something an interface designer can do, maybe because he wants it to be treated that way. And it leaves the path open to optimize things for cases where the "const" is useful.
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.
According to the documentation for NSString's method -UTF8String:
The returned C string is automatically
freed just as a returned object would
be released; you should copy the C
string if it needs to store it outside
of the autorelease context in which
the C string is created.
So under retain/release memory management, the following method:
- (const char*) giveMeACString
{
NSString* string = #"I'm a string!";
return [string UTF8String];
}
is fine, so long as the calling method treats the returned const char* as it would an autoreleased object.
However, under garbage collection there isn't an autorelease context, as far as I'm aware. And C types aren't garbage collected, so it doesn't look like the GC will treat the returned pointer as it would a returned object.
What is its lifespan tied to? Is it still freed at a point in the thread's runloop that is reliably `later on', or does it behave differently under GC than under non-GC?
I think the memory is allocated from garbage collected memory and the return type is __strong const char*. This means that it will be collected in the normal way when it is not reachable from the root set of pointers.
That basically means you need to store it in a pointer variable that is marked as __strong or it will be collected at some point.
I'd speculate that an immutable string maintains a reference to the UTF8 version of itself, so it only has to calculate it once and therefore the UTF8 string probably won't go away until the NSString does which is why you don't have to worry about it disappearing normally.
Since you did not explicitly allocate those spaces, you do not need to worry about deallocation.