Object removal from NSMutableArray - nsmutablearray

I am having some problem working with "removeObjectAtIndex" method in order to remove some a certain type of string literal in a mutable array, using the following technique (I wrote this in a text editor):-
#import <Foundation/Foundation.h>
#interface Test: NSObject
#property NSMutableArray *elements;
-(void) method;
#end
#implementation Test
#synthesize elements;
-(void) method{
elements= [[NSMutableArray alloc] init];
[elements addObjectsFromArray:#[#"c", #"a", #"b", #"c", #"c", #"d", #"c", #"c", #"e", #"c"]];
NSLog(#"number of elements initially- %d", elements.count);
int index= elements.count-1;
for(id i in [elements reverseObjectEnumerator])
{
// static int index= elements.count-1;
NSLog(#"index- %d", index);
if([i isEqual:#"c"]){
[elements removeObjectAtIndex:index];
NSLog(#"Object in place of removed object- %#, at index- %d", [elements objectAtIndex:index], index);
NSLog(#"No. of elements left after the removal- %d", elements.count);
}
index--;
}
}
#end
int main()
{
Test *test= [[Test alloc] init];
[test method];
NSLog(#"elements- %#", test.elements);
}
On running this in the terminal, I get an out of bounds exception.
cd '~/Desktop/Source Code/'; clang -framework Foundation -w ObjectRemovalInArray.m -o ~/Desktop/Binaries/ObjectRemovalInArray && ~/Desktop/Binaries/ObjectRemovalInArray
2018-06-18 20:25:25.797 ObjectRemovalInArray[4684:731973] number of elements initially- 10
2018-06-18 20:25:25.797 ObjectRemovalInArray[4684:731973] index- 9
2018-06-18 20:25:25.798 ObjectRemovalInArray[4684:731973] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 9 beyond bounds [0 .. 8]'
*** First throw call stack:
(
0 CoreFoundation 0x00007fff345f632b __exceptionPreprocess + 171
1 libobjc.A.dylib 0x00007fff5b764c76 objc_exception_throw + 48
2 CoreFoundation 0x00007fff34637634 _CFThrowFormattedException + 202
3 CoreFoundation 0x00007fff34515290 __CFStringDecodeByteStream3 + 0
4 ObjectRemovalInArray 0x00000001007dbbaf -[Test method] + 799
5 ObjectRemovalInArray 0x00000001007dbd54 main + 68
6 libdyld.dylib 0x00007fff5c37e015 start + 1
7 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
Abort trap: 6
Bascially, i kind of understand this problem by realizing that in the beginning of the loop, I'm having the "i" (of type id) pointer point to the last object in the array which also happens to be the object that is up for deletion. And when that happens, the mutable-array shrinks by 1 memory location leaving the 10th one (index-9) inaccessible as it becomes deallocated. So by then the "i" pointer needed to have moved a spot back to the next object, but that doesn't happen under the hood. Should I fix this using a sentinel of sorts in the end? Because did try using "nil" by putting it at the end of the array. But it wouldn't take in (void *)object. How do I fix this? Any assist would be of much help to me. Please note that I want to solve the problem using fast-enumeration only.
Strangely, the problem doesn't arise inside Xcode. I have used the same code snippet there; built and run it as a part of a larger project. No issues there. No exceptions thrown then.

Related

Core Foundation memory leaks

+ (CFArrayRef)getLinesForText:(NSAttributedString *)text width:(CGFloat)width {
UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, width, 10000)];
CTFramesetterRef frameSetterRef = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)text);
CTFrameRef frameRef = CTFramesetterCreateFrame(frameSetterRef, CFRangeMake(0, 0), path.CGPath, nil);
CFArrayRef lines = CFArrayCreateCopy(NULL, CTFrameGetLines(frameRef));
CFRelease(frameRef);
CFRelease(frameSetterRef);
return lines;
}
When using CoreText , I have some code like this. After called the method , I use CFRelease to release the returned lines . But when profile with leaks , these codes still have leaks ?How can this happened ?
It is my fault. I need use CFAutorelease when the method returns, rather than let the caller release the returned lines.

Using GLUT after fork on OSX Sierra [duplicate]

This question already has an answer here:
Why can't I use cocoa frameworks in different forked processes?
(1 answer)
Closed 6 years ago.
Before Sierra, I used to be able to initialize GLUT on the child process after forking the original process. With the latest version of Sierra, this seems to have changed. The following program crashes with a segmentation fault. If I instead move all the glut functions to the parent process, everything works. Why is there a difference between using the parent/child process?
#include <stdlib.h>
#include <GLUT/glut.h>
void pass(void){
}
int main(int argc, char* argv[]) {
pid_t childpid;
childpid = fork();
if (childpid == 0){
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(100,100);
glutCreateWindow("test");
glutDisplayFunc(pass);
glGetError();
glutMainLoop();
}else{
sleep(5);
}
exit(1);
}
The segmentation fault I get:
Crashed Thread: 0 Dispatch queue: com.apple.main-thread
Exception Type: EXC_BAD_INSTRUCTION (SIGILL)
Exception Codes: 0x0000000000000001, 0x0000000000000000
Exception Note: EXC_CORPSE_NOTIFY
Termination Signal: Illegal instruction: 4
Termination Reason: Namespace SIGNAL, Code 0x4
Terminating Process: exc handler [0]
Application Specific Information:
BUG IN CLIENT OF LIBDISPATCH: _dispatch_main_queue_callback_4CF called from the wrong thread
crashed on child side of fork pre-exec
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 libdispatch.dylib 0x00007fffe8e7bd21 _dispatch_main_queue_callback_4CF + 1291
1 com.apple.CoreFoundation 0x00007fffd3c7bbe9 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
2 com.apple.CoreFoundation 0x00007fffd3c3d00d __CFRunLoopRun + 2205
3 com.apple.CoreFoundation 0x00007fffd3c3c514 CFRunLoopRunSpecific + 420
4 com.apple.Foundation 0x00007fffd57e1c9b -[NSRunLoop(NSRunLoop) limitDateForMode:] + 196
5 com.apple.glut 0x0000000104f39e93 -[GLUTApplication run] + 321
6 com.apple.glut 0x0000000104f46b0e glutMainLoop + 279
7 a.out 0x0000000104f24ed9 main + 121 (main.c:18)
8 libdyld.dylib 0x00007fffe8ea4255 start + 1
fork() is not creating a thread, it forks the process. After calling fork you have two processes with nearly identical address space contents, but their address spaces are protected from each other. The general rule regarding fork() is, that the only sensisble thing to do after a fork in the child process, is to replace the process image with execve(); doing anything else requires a lot of foresight in the program's design.
Thread's are created in a different way. I suggest you use the actual threading primitives offered by your programming language of choice.
That being said, many OSs and GUI libraries want a process' GUI parts to run in the main thread, so that could be part of the reason as well. Also be aware that OpenGL and multithreading is a little bit finicky.

Trying to multithread program. C++/CLI

Hey i'm trying to multithread my program in c++/cli but i'm having problems with creating the threads the code im using is:
private: Void startThread() {
MoveProj.Velocity = Variables.Velocity;
MoveProj.ProjectilePos = Projectile1.ProjectilePos;
Thread^ MotionThread1 = gcnew Thread(gcnew ParameterizedThreadStart(MoveProj, MotionThread::MoveProjectile));
Thread^ MainThread = gcnew Thread(gcnew ThreadStart());
}
but i'm getting the errors
Error 44 error C3350: 'System::Threading::ParameterizedThreadStart' : a delegate constructor expects 2 argument(s) c:\users\gaz\documents\visual studio 2012\projects\projectilemotion\projectilemotion\Simulation.h 344
Error 89 error C3350: 'System::Threading::ParameterizedThreadStart' : a delegate constructor expects 2 argument(s) c:\users\gaz\documents\visual studio 2012\projects\projectilemotion\projectilemotion\Simulation.h 344
Error 45 error C3350: 'System::Threading::ThreadStart' : a delegate constructor expects 2 argument(s) c:\users\gaz\documents\visual studio 2012\projects\projectilemotion\projectilemotion\Simulation.h 345
Error 90 error C3350: 'System::Threading::ThreadStart' : a delegate constructor expects 2 argument(s) c:\users\gaz\documents\visual studio 2012\projects\projectilemotion\projectilemotion\Simulation.h 345
Error 43 error C3867: 'MotionThread::MoveProjectile': function call missing argument list; use '&MotionThread::MoveProjectile' to create a pointer to member c:\users\gaz\documents\visual studio 2012\projects\projectilemotion\projectilemotion\Simulation.h 344
Error 88 error C3867: 'MotionThread::MoveProjectile': function call missing argument list; use '&MotionThread::MoveProjectile' to create a pointer to member c:\users\gaz\documents\visual studio 2012\projects\projectilemotion\projectilemotion\Simulation.h 344
any help with this would be a great help as its for my college(British so senior year for americnas i think) computing project and my tutor wants it in relatively soon.
The error message is telling you what to do:
function call missing argument list;
use '&MotionThread::MoveProjectile' to create a pointer to member
^
Therefore, here's the correct syntax:
Thread^ MotionThread1 = gcnew Thread(
gcnew ParameterizedThreadStart(MoveProj, &MotionThread::MoveProjectile));
^
For the other one, you're currently trying to create a delegate, without telling it what method the delegate should point to. Try something like this:
Thread^ MainThread = gcnew Thread(gcnew ThreadStart(this, &MyClass::MainMethod));
^^^^^^^^^^^^^^^^^^^^^^^^^^
Edit
I didn't read through your full code. If you expect people to take their time to help you, you need to take some time & spend the effort to distill it down to just what's needed.
I will, however, comment on the errors you're getting.
error C2440: 'initializing' :
cannot convert from 'MotionThread' to 'MotionThread ^'
You've got a variable somewhere that's a reference type, but you're using it without the ^. This is valid C++/CLI, but none of the managed APIs will work with that easily. Switch the member to a ^ and use gcnew.
error C3352: 'float Allformvariables::CalcCurrentVelocity(System::Object ^)' :
the specified function does not match the delegate type 'void (void)'
As the error message says: You're trying to construct a delegate that doesn't take any parameters and returns void, and the method you're passing doesn't match that. Either fix the method or switch to a different delegate type.
error C3754: delegate constructor: member function 'MotionThread::MoveProjectile'
cannot be called on an instance of type 'MotionThread'
I have a feeling this one will go away when you add the missing ^ that I mentioned above.

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?)

MemoryLeaking from array with dictionaries

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.

Resources