I understand the definition of a Memory Leak but couldn't find anything referred to Semantical or Semantic Memory Leak and the differences to memory leak.
Example for a memory leak:
#include <stdlib.h>
void function_which_allocates(void) {
/* allocate an array of 45 floats */
float *a = malloc(sizeof(float) * 45);
/* additional code making use of 'a' */
/* return to main, having forgotten to free the memory we malloc'd */
}
int main(void) {
function_which_allocates();
/* the pointer 'a' no longer exists, and therefore cannot be freed,
but the memory is still allocated. a leak has occurred. */
}
Definition (Semantical garbage)
A variable which the program will never use again, but
still keeps a reference to it, is called semantic garbage.
In other words, imagine allocating an array in your main program and using it only in the first few lines, and after you're done not freeing it. basically the major difference between a semantic memory leak and a memory leak is that, in a memory leak you have no reference to the unfreed array, however in a semantic leak you actually have a reference to it although you're no longer using it.
Definition (Semantical garbage)
A variable which the program will never use again, but
still keeps a reference to it, is called semantic garbage.
class Huge {
Huge() { // Constructor:
// Allocates lots of data and stores
// it in the newly created object
}
}
void f() {
Huge semanticGarbage = new Huge();
heavy.computation(new Indeed(100));
System.exit(1);
}
All sophisticated GC algorithms contend in vain against semantic garbage.
Reference:
Technion CS 234319: Programming Languages Course
(Lecture) Chapter 5 Storage 5.5 Automatic memory management - Semantical memory leak
Related
I have some event from C++ written library which works in background thread:
virtual void OnData(const char* data)
{
NSLog(#"Here 'data' string is present %s", data);
#autoreleasepool {
NSString* sData= [NSString stringWithCString:data encoding:NSUTF8StringEncoding];
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"Here _sometimes_ 'data'(%s) is nil (\0). But sData is always present %#", data, sData);
[callback OnData:sData];
});
};
}
And sometimes I have NULL(I suspect its garbage actually) in dispatch_async block in argument variable. But local NSString variable is always here. Why?
P.S. Do I actually must use #autoreleasepool in this situation?
You have no assurances about the lifespan of the buffer that const char *data was pointing to by the time the async block is performed. The data could be dangling pointer by that point (and should be assumed to be so). It's very dangerous to use C-style pointers in any asynchronous references or outside the context they were originally created.
You should either use memory managed objects (e.g. NSData, NSString, etc.) or, if you insist on using C-style pointers and need to reference this pointer in the asynchronous block, copy the data to your own buffer, use that buffer, and then free it when you're done using that buffer in your asynchronous routine. In this case, you have your sData, so just don't refer to data after that point, and you'll be fine.
P.S. You later ask whether you must use #autoreleasepool in this situation.
In short, in most cases, no additional autorelease pool is needed. Notably, when using Grand Central Dispatch (e.g. dispatch_async), it has its own autorelease pools, so you don't have to create one. And, when your main thread yield back to its run loop, again, it's pool is drained. In short, you only need manually created autorelease pools when instantiating your own NSThread objects.
Having said that, sometimes you will introduce autorelease pools if doing significant memory intensive operations prior to yielding back to the run loop. In that case, you'll add autorelease pools in order to reduce the peak memory usage of the app. But this would not appear to be one of those cases.
If you had something like this:
void CallOnData()
{
char *test = malloc(5 * sizeof(char));
strcpy(test, "test");
OnData(test);
free(test);
}
You should expect data to be "NULL" in the block.
And autorelease is not needed, assuming you're using ARC, which you should be.
I am using ARC for my iOS project and am using a library called SSKeychain to access/save items to the keychain. I expect my app to access keychain items once every 10 seconds or so (to access API security token) at peak load and as such I wanted to test this library to see how it handles when called frequently. I made this loop to simulate an insane amount of calls and noticed that it bleeds a significant amount (~75 mb) of memory when run on an iPhone (not simulator):
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
dispatch_async(dispatch_get_main_queue(), ^{
NSUInteger beginMemory = available_memory();
for (int i = 0; i < 10000; ++i) {
#autoreleasepool{
NSError * error2 = nil;
SSKeychainQuery* query2 = [[SSKeychainQuery alloc] init];
query2.service = #"Eko";
query2.account = #"loginPINForAccountID-2";
query2.password = nil;
[query2 fetch:&error2];
}
}
NSUInteger endMemory = available_memory();
NSLog(#"Started with %u, ended with %u, used %u", beginMemory, endMemory, endMemory-beginMemory);
});
return YES;
}
static NSUInteger available_memory(void) {
// Requires #import <mach/mach.h>
NSUInteger result = 0;
struct task_basic_info info;
mach_msg_type_number_t size = sizeof(info);
if (task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &size) == KERN_SUCCESS) {
result = info.resident_size;
}
return result;
}
I am using SSKeychain which can be found here. This test bleeds about ~75 mb of memory regardless if things are actually stored on the keychain.
Any ideas what is happening? Is my testing methodology flawed?
I ran your code under the Leaks Instrument and this is what I saw from the Allocations track -
Which is what you would expect - a lot of memory allocated during the loop and then it is released.
Looking at the detail you see -
Persistent bytes on the heap of 2.36MB - This is the memory actually used by the app 'now' (i.e. after the loop with the app 'idling')
Persistent objects of 8,646 - again, the number of objects allocated "now".
Transient objects 663,288 - The total number of objects that have been created on the heap over the application lifetime. You can see from the difference between transient and persistent that most have been released.
Total bytes of 58.70MB - This is the total amount of memory that has been allocated during execution. Not the total of memory in use, but the total of the amounts that have been allocated regardless of whether or not those allocations have been subsequently freed.
The difference between the light and dark pink bar also shows the difference between the current 'active' memory use and the total use.
You can also see from the Leak Checks track that there are no leaks detected.
So, in summary, your code use a lot of transient memory as you would expect from a tight loop, but you wouldn't see this memory use in the normal course of your application execution where the keychain was accessed a few times every second or minute or whatever.
Now, I would imagine that having gone to the effort of growing the heap to support all of those objects, iOS isn't going to release that now freed heap memory back to the system straight away; it is possible that your app may need a large heap space again later, which is why your code reports that a lot of memory is in use and why you should be wary of trying to build your own instrumentation rather than using the tools available.
You should use Instruments to figure out where/what is causing a leak. Its a very good tool to know how to use.
This article is a little dated but you should get the basic gist.
Ray Wenderlich - Instruments
Going off of Paulw11's comment I stumbled across this,
From NSAutoreleasePool Class Reference:
The Application Kit creates an autorelease pool on the main thread at
the beginning of every cycle of the event loop, and drains it at the
end, thereby releasing any autoreleased objects generated while
processing an event.
So when you check it with instruments make sure the event loop has had time to finish. Maybe all you need to do is let the program keep running and then pause the debugger and check instruments again.
I'm doing some research on how iPhone manage the heap and stack but it's very difficult to find a good source of information about this. I'm trying to trace how a password is kept in memory, even after the NSString is deallocated.
As far as I can tell, an iPhone will not clear the memory content (write zeros or garbage) once the release count in ARC go down to 0. So the string with the password will live in memory until that memory position is overridden.
There's a debug option in Xcode, Malloc Scribble, to debug memory problems that will fill deallocated memory with 0x55, by enabling/disabling this option (and disabling Zombies), and after a memory dump of the simulator (using gcore) I can check if the content has been replaced in memory with 0x55.
I wonder if this is something that can be done with the Apple Store builds, fill deallocated memory with garbage data, if my assumption that iPhone will not do that by default is correct or not, or if there's any other better option to handle sensitive data in memory, and how it should be cleared after using it (Mutable data maybe? write in that memory position?)
I don't think that there's something that can be done on the build settings level. You can, however, apply some sort of memory scrubbing yourself by zeroing the memory (use memset with the pointer to your string).
As #Artal was saying, memset can be used to write in a memory position. I found this framework "iMAS Secure Memory" that can be useful to handle this:
The "iMAS Secure Memory" framework provides a set of tools for
securing, clearing, and validating memory regions and individual
variables. It allows an object to have it's data sections overwritten
in memory either with an encrypted version or null bytes
They have a method that it should be useful to clear a memory position:
// Return NO if wipe failed
extern inline BOOL wipe(NSObject* obj) {
NSLog(#"Object pointer: %p", obj);
if(handleType(obj, #"", &wipeWrapper) == YES) {
if (getSize(obj) > 0){
NSLog(#"WIPE OBJ");
memset(getStart(obj), 0, getSize(obj));
}
else
NSLog(#"WIPE: Unsupported Object.");
}
return YES;
}
I've been working through a handful of directX tutorials. They all mention D3DXCreateTextureFromFileEx
for loading an image from a file into video memory. However, nobody (that I've seen), talks about how to free up that memory. Can I just call free() on the pointer that is returned?
Like almost all of the DirectX API, when you create a new object, it's returned as a pointer to a COM interface. In your case you get a pointer to an IDirect3DTexture9 interface.
When you want to release these resources, you use the normal COM method for disposing of reference-counted interfaces, by calling Release() on the pointer:
IDirect3DDevice9 *pTexture = NULL;
D3DXCreateTextureFromFileEx( /* ... */, &pTexture);
// ... use the texture .....
// release interface
pTexture->Release();
pexture = NULL;
This function is in a loop. When I run the program, the line with IntPtr is giving me memory problems, I've put delete[], but it still doesn't solve the memory problem, can anyone help please? thanks
void showImage(IplImage *img,System::Windows::Forms::PictureBox^ picturebox)
{
IntPtr ip(new unsigned char[img->widthStep*img->height]); // this line causing memory usage to keep going up very fast
//memcpy(ip.ToPointer(),img->imageData,img->widthStep*img->height);
//picturebox->Image = gcnew Bitmap(img->width,img->height, img->widthStep, System:rawing::Imaging::PixelFormat::Format24bppRgb, ip);
delete[] ip;
}
This is C++\CLI
It is rather sad that this code compiles, but that is by design. The delete operator applied to a managed type doesn't actually free any memory. It calls the IDisposable::Dispose() method on the passed object. It is rather sad that this even works, the IntPtr gets boxed to turn it into an object and then checked to see if it implements the IDisposable interface. It doesn't of course, nothing happens.
You have to pass the pointer that you got back from the new operator. Don't forget to do this in a finally block so an exception cannot cause a leak.
Btw, there are more complications in the code that you commented. The Bitmap constructor you use requires you to keep the IntPtr valid, you cannot release the memory until the Bitmap is no longer used. So using delete isn't actually valid. Consider using Bitmap.LockBits() instead to get a pointer to a Bitmap that manages its own memory. And watch out for stride.