MemoryLeaking from array with dictionaries - memory-leaks

I have my function getAllData, which is returning an array with dictionaries.
- (NSArray *)getAllData {
NSMutableArray *result = [[NSMutableArray alloc] init];
NSArray *data = [skiResorts sortedArrayUsingFunction:comparator context:NULL];
NSString *currentLetter = #"A";
NSMutableArray *array = [[NSMutableArray alloc] init] ;
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init] ;
if ([data count] > 0) {
for (SkiResort *resort in data) {
if ([resort.name hasPrefix:currentLetter]) {
// Same letter as before.
// Add current SkiResort to temporary array.
[array addObject:resort];
} else {
// New letter.
// Add previous header/row data to dictionary.
[dict setValue:currentLetter forKey:#"header"];
[dict setValue:array forKey:#"row"];
// Add dictionary to final result array.
[result addObject:dict];
// Startover ...
[array removeAllObjects];
[dict removeAllObjects];
// Prepare for next letter.
currentLetter = [resort.name substringToIndex:1];
// Add current SkiResort to temporary array.
[array addObject:resort];
}
}
// Add previous header/row data to dictionary.
[dict setValue:currentLetter forKey:#"header"];
[dict setValue:array forKey:#"row"];
// Add dictionary to final result array.
[result addObject:dict];
}
[array release];
[dict release];
return [result autorelease];
}
Can anyone see obvious memory leaks in my code? I get memory leak array, dict, and result...

From the code, I have to ask: you're aware that addObject: doesn't copy the object? So setting values to dict, then adding it to result, then removing everything from dict just leaves an empty dictionary in result? I think you probably want to use the 'copy' method in there, to make copies of the array and dictionary. Or, even better, just create the dictionary when you add it to result using one of the class methods.
Anyway, since I can't see any leaks in that, much more likely is that whoever receives the result of getAllData subsequently leaks it. If for some crazy reason you had somewhere a stray:
[[object getAllData] retain];
Then the leaks tool would identify a leak of array, dict and result and point you to getAllData as the method in which they were originally created.

I really should say before I answer my knowledge on this is VERY limited, so take that into consideration. But it seems to me like you have a container inside a container. And when u reserve memory for that you have to backwards unreserve it.
For example, Store n (B_Containers) in Container A reserves n_B containers and 1 A container. To unreserve the memory you need to unreserve n B_Containers first before you delete A or all B_Containers will be withou reference and floating around in your memory.

Related

How to satisfy C6011 error with dynamically allocated array of structures

We have a heap-allocated array of custom structures that is pointed to by a local pointer. The pointer to the array is checked for nullptr. However, during my loop, VC++ complains that the first attempt to use an indexed entry in the array is "Dereferencing NULL pointer 'ppi'".
I'm having a dumb moment here I think, but there doesn't seem to be any way to satisfy the 6011 warning... how do I correct this scenario?
I have included some snippets of code to briefly illustrate the code in question.
// Previously, SystemInfoObject.PeripheralPortInfo is heap-alloc'd to contain
// multiple PeripheralInfo structures, and
// SystemInfoObject.PeripheralPortInfoCount is adjusted to the number
// of elements.
PeripheralInfo *ppi = nullptr;
ppi = SystemInfoObject.PeripheralPortInfo; // Set our local pointer
if (ppi != nullptr)
{
for (int i = 0; i < SystemInfoObject.PeripheralPortInfoCount; i++)
{
if (_tcsncmp(ppi[i].PortName, _T("\\\\"), 2) == 0) // C6011
{
// Some code
}
}
}
Visual Studio strikes again, I didn't see the loop condition that required certain code later on to change the pointer ppi and the null condition was never re-checked on subsequent loop iterations.
Wish I could delete my question! All set!

C++ : Strings, Structures and Access Violation Writing Locations

I'm attempting to try and use a string input from a method and set that to a variable of a structure, which i then place in a linked list. I didn't include, all of code but I did post constructor and all that good stuff. Now the code is breaking at the lines
node->title = newTitle;
node->isbn = newISBN;
So newTitle is the string input from the method that I'm trying to set to the title variable of the Book structure of the variable node. Now, I'm assuming this has to do with a issue with pointers and trying to set data to them, but I can't figure out a fix/alternative.
Also, I tried using
strcpy(node->title, newTitle)
But that had an issue with converting the string into a list of chars because strcpy only uses a list of characters. Also tried a few other things, but none seemed to pan out, help with an explanation would be appreciated.
struct Book
{
string title;
string isbn;
struct Book * next;
};
//class LinkedList will contains a linked list of books
class LinkedList
{
private:
Book * head;
public:
LinkedList();
~LinkedList();
bool addElement(string title, string isbn);
bool removeElement(string isbn);
void printList();
};
//Constructor
//It sets head to be NULL to create an empty linked list
LinkedList::LinkedList()
{
head = NULL;
}
//Description: Adds an element to the link in alphabetical order, unless book with
same title then discards
// Returns true if added, false otherwise
bool LinkedList::addElement(string newTitle, string newISBN)
{
struct Book *temp;
struct Book *lastEntry = NULL;
temp = head;
if (temp==NULL) //If the list is empty, sets data to first entry
{
struct Book *node;
node = (Book*) malloc(sizeof(Book));
node->title = newTitle;
node->isbn = newISBN;
head = node;
}
while (temp!=NULL)
{
... //Rest of Code
Note that your Book struct is already a linked list implementation, so you don't need the LinkedList class at all, or alternatively you don't need the 'next' element of the struct.
But there's no reason from the last (long) code snippet you pasted to have an error at the lines you indicated. node->title = newTitle should copy the string in newTitle to the title field of the struct. The string object is fixed size so it's not possible to overwrite any buffer and cause a seg fault.
However, there may be memory corruption from something you do further up the code, which doesn't cause an error until later on. The thing to look for is any arrays, including char[], that you might be overfilling. Another idea is you mention you save method parameters. If you copy, it's ok, but if you do something like
char* f() {
char str[20];
strcpy(str, "hello");
return str;
}
...then you've got a problem. (Because str is allocated on the stack and you return only the pointer to a location that won't be valid after the function returns.) Method parameters are local variables.
The answer you seek can be found here.
In short: the memory malloc returns does not contain a properly constructed object, so you can't use it as such. Try using new / delete instead.

C++/CLI reference not initialized to nullptr on subsequent entries into local block

I thought in C++/CLI declaring a local reference variable without an explicit initial value always initialized it to nullptr. I'm finding that this doesn't occur on the second and later entries into a local block. Here's the sample code.
void main()
{
for (int i=0; i<6; i++)
{
switch (i)
{
case 2:
Console::WriteLine("i={0} localI and hashTable no longer in scope", i);
break;
default:
{
// Declare local reference variable
Hashtable^ hashTable;
Int32 localI;
Console::WriteLine("i={0} localI={1} {2}",
i, localI,
hashTable == nullptr ? "hashTable=nullptr" : "hashTable NOT SET to nullptr"
);
hashTable = gcnew Hashtable();
localI = i+1;
}
break;
}
}
}
The output from this is:
i=0 localI=0 hashTable=nullptr
i=1 localI=1 hashTable NOT SET to nullptr
i=2 localI and hashTable no longer in scope
i=3 localI=2 hashTable NOT SET to nullptr
i=4 localI=4 hashTable NOT SET to nullptr
i=5 localI=5 hashTable NOT SET to nullptr
If I add explicit initialization
Hashtable^ hashTable = nullptr;
Int32 localI = 99;
Then each loop reinitializes the reference and localI
i=0 localI=99 hashTable=nullptr
i=1 localI=99 hashTable=nullptr
i=2 localI and hashTable no longer in scope
i=3 localI=99 hashTable=nullptr
i=4 localI=99 hashTable=nullptr
i=5 localI=99 hashTable=nullptr
This seems to contradict what I found here on MSDN which says:
"The following code example shows that when handles are declared and not explicitly initialized, they are default initialized to nullptr."
This is by design, the CLR only initializes local variables on method entry. Scope blocks inside a method are a language implementation detail that disappears after compilation. Other managed languages are alike, VB.NET behaves the exact same way. C# would too, but doesn't permit this kind of code due to its definite assignment rule.
This behavior otherwise simplifies the runtime implementation greatly. The jitter simply generates code to blast the stackframe to zero at entry.

Leaking when tried to free vector element

please help to figure this out.
I have some leaking code, and I don't know how to handle it
vector <ItemClass> items( 10 );
items[1] = ItemClass( "DVD Player", 560 );
items[5] = * new ItemClass( "Blu Ray Player", 900 );
How should I free memory for items[5] ?
I'm getting error on my attempts of freeing memory
delete &items[5];
delete [] &items[5];
I even tried something like
ItemClass * delItem = &items[5];
items[5] = item4;
delete delItem;
I'm getting "corruption of the heap" in VS2010 Ultimate
There is a strange use and mix up of storing new-allocated objects in vectors in your code. Usually you should handle lists all in the same way. Thus my examples below will be more explicit, and independent from each other which should help you understand the differences.
Use delete for objects only. See code below.
Use delete [] for "native" arrays only, not for vector or similar container classes or objects inside them.
I will not give an example for arrays though, since arrays might be more confusing.
Default example stack:
vector <ItemClass> items( 10 );
// does not need to be deleted because item is on the stack
ItemClass item("device1", "10");
items.push_back(item);
Default example with heap allocation:
vector <ItemClass*> items( 10 );
ItemClass* pItem = new ItemClass("device2", "20");
items.push_back(pItem);
// delete all items inside vector
for (int i = 0; i < items.size(); i++)
{
ItemClass* pToDelete = items[i];
delete pToDelete;
items.erase(i);
}
The following examples should be avoided and are for clarifying things up only! Use at own risk.
Storing addresses of stack variables:
vector <ItemClass*> items( 10 );
// does not need to be deleted because item is on the stack
ItemClass item("device3", "30");
items.push_back( &item ); // storing a reference to item
// No need to delete this item that points to something on the stack.
// However you might not be able to tell items apart which have been
// created on the heap or the stack, so just dont do it.
If you mix up with the example before and store references and pointers you must handle it yourself. My recommendation: Do not do this.
Storing dereferenced items:
vector <ItemClass> items( 10 );
ItemClass* pItem = new ItemClass("device4", "40");
items.push_back(*pItem);
// must be deleted because allocated on the heap
// Again you can not tell which item is allocated on stack or heap. Avoid this.
You don't call delete on objects that you don't own. You don't own items[5]. The items vector owns it.
What you need to delete is the ItemClass object that you are currently leaking, which is the one you are creating via new ItemClass(...) and then copying to items[5].
ItemClass *temp = new ItemClass("Blue Ray Player", 900);
items[5] = *temp;
delete temp;
If you want to remove items[5] from the vector, ask the vector to remove it:
items.erase(items.begin() + 5);
Note that this may be rather inefficient, because all later items in the vector have to be moved down one position, which entails calling the ItemClass assignment operator once for each moved item.
You might want to use a vector of pointers to ItemClass instead, or a vector of shared_ptrs, or a boost::ptr_vector.

NSMutableArray goes SIGABRT in multithreaded app... but I _am_ doing #synchronized!

Sorry... shame - I didn't run debug mode so the error showed up on the wrong line. In debug-mode, and showing the right line, the error was a simple "dont access an array outside its bounds"-error (typo - i referred to one array but access was to another)
Why does accessing the count of an NSMutableArray produce SIGABRT when I empty the NSMutableArray from another thread? I thought the #synchronized was supposed to do as it's name implies?
NSMutableArray *sourceImageRepArray;
...
#synchronized(self)
{
NSLog(#"singleton 1 %p", self);
unsigned long count = sourceImageRepArray.count; //SIGABRT here!
...
Don't know how much extra code you want me to share... this is the code that triggers it:
#synchronized([Singleton sharedSingleton])
{
NSLog(#"singleton 2 %p", [Singleton sharedSingleton]);
int i, n;
n = [filenames count];
for(i=0; i<n; i++){
ImageRep *item = [[ImageRep alloc] init];
[item setPath:[filenames objectAtIndex:i]];
[[Singleton sharedSingleton].targetImageRepArray insertObject:item atIndex: [targetImageBrowser indexAtLocationOfDroppedItem]];
[item release];
[[Singleton sharedSingleton] removeImageRepFromArray:[Singleton sharedSingleton].sourceImageRepArray withPath:[filenames objectAtIndex:i]];
}
}
singleton 1 == singleton 2:
2011-02-08 07:22:03.265 Crash[60001:5d03] singleton 1 0x200047680
2011-02-08 07:22:03.433 Crash[60001:a0f] singleton 2 0x200047680
why is it not synchronizing?! What else could be going on?
are you sure your self and [Singleton sharedSingleton] are the same object?
Sorry... shame - I didn't run debug mode so the error showed up on the wrong line. In debug-mode, and showing the right line, the error was a simple "dont access an array outside its bounds"-error (typo - i referred to one array but access was to another)
So the solution to my problem was:
Don't do NSLog-debugging in release, it may mark errors on the wrong lines. (sometimes, in multithreaded apps, I guess?)

Resources