array index blows up obj c - objective-c

I am writing an iPhone app in Xcode 4.6.3.
I don't really know how to ask this question, but during operation, an array index goes from 0, which is hardcoded in a method, to 58911 for some reason. The chain is:
- (void)syncInitialState
{
[self syncState:0]; //value starts hardcoded here
}
then:
- (void)syncState:(int)index
{
self.state = [macrostate getState:index];
[self syncState];
}
in Macrostate:
- (NPState *)getState:(int)index
{
int *singleArray = {&index};
NSPointerArray *pointerArray = [self subsetFromIntArray:singleArray];
return (__bridge NPState *)[pointerArray pointerAtIndex:0]; //only one object
}
finally:
- (NSPointerArray *)subsetFromIntArray:(int *)intArray
{
NSPointerArray *subset = [NSPointerArray strongObjectsPointerArray];
for (int i=0; i<sizeof(intArray); i++) {
[subset addPointer:[pointerArrayOfStates pointerAtIndex:intArray[i]]]; //fails
}
return subset;
}
Obviously it fails because 58911 is outside the bounds of the pointer array. I have never seen this before. Thanks for reading.
It might help to know that the error is: * Terminating app due to uncaught exception 'NSRangeException', reason: ' -[NSConcretePointerArray pointerAtIndex:]: attempt to access pointer at index 58911 beyond bounds 4' ** First throw call stack: (0x1caa012 0x10e7e7e 0x1ca9deb 0xb1c1ab 0xd8ae 0xd7a5 0x47c6 0x485e 0x567f 0x5d95 0x2d3f 0x10d1c7 0x10d232 0x5c3d5 0x5c76f 0x5c905 0x65917 0x29c5 0x29157 0x29747 0x2a94b 0x3bcb5 0x3cbeb 0x2e698 0x1c05df9 0x1c05ad0 0x1c1fbf5 0x1c1f962 0x1c50bb6 0x1c4ff44 0x1c4fe1b 0x2a17a 0x2bffc 0x26fd 0x2625) libc++abi.dylib: terminate called throwing an exception

You can't use sizeof to get the length of the int array. You need to add a "length" parameter to your subsetFromIntArray: method and use that instead of sizeof.

Related

Why does this conditional cause an error?

I have a method that contains a few conditionals. The first conditional works fine and does not cause any problems. However, the second one causes the app to crash.
- (void)didReceiveGaiaGattResponse:(CSRGaiaGattCommand *)command
{
GaiaCommandType cmdType = [command getCommandId];
NSData *requestPayload = [command getPayload];
uint8_t success = 0;
NSLog(#"cmdType: %li", (long)cmdType);
[requestPayload getBytes:&success range:NSMakeRange(0, sizeof(uint8_t))];
if (cmdType == GaiaCommand_GetCurrentBatteryLevel && requestPayload.length > 1)
{
uint16_t value = 0;
[requestPayload getBytes:&value range:NSMakeRange(1, sizeof(uint16_t))];
NSInteger battery = CFSwapInt16BigToHost(value);
[self sendEventWithName:someDEVICE_BATTERY_CHANGED body:#{#"batteryLevel":[NSNumber numberWithInteger:battery]}];
return;
}
else if (cmdType == GaiaCommand_GET_FBC && requestPayload.length > 1)
{
uint16_t value = 0;
[requestPayload getBytes:&value range:NSMakeRange(1, sizeof(uint16_t))];
NSInteger feedbackCancellationMode = CFSwapInt16BigToHost(value);
[self sendEventWithName:FEEDBACK_CANCELLATION_MODE body:#{#"feedbackCancellationMode": [NSNumber numberWithInt:feedbackCancellationMode]}];
return;
}
//do more stuff
}
The conditional
if (cmdType == GaiaCommand_GetCurrentBatteryLevel &&
requestPayload.length > 1)
works without problems.
However, the conditional
else if (cmdType == GaiaCommand_GET_FBC && requestPayload.length > 1)
causes the following warning in xcode
Implicit conversion loses integer precision: 'NSInteger' (aka 'long')
to 'int'
In addition, I also saw the error message in the debugger
* Terminating app due to uncaught exception 'NSRangeException', reason: '* -[_NSInlineData getBytes:range:]: range {1, 2} exceeds
data length 2'
Consider what this is telling you:
Terminating app due to uncaught exception 'NSRangeException', reason:
'-[_NSInlineData getBytes:range:]: range {1, 2} exceeds data length 2'
Your data object is 2 bytes in length. The first byte, at position 0, is (according to your code) the success value. That leaves one more byte at position 1 to handle. But your code is attempt to copy 2 bytes out of it — that's the range {1, 2} in the message; a range starting at position 1 and with a length of 2. You're reading past the end of the data.
You have to check that the data has enough data to satisfy the -getBytes:... call you're attempting to make. You may also need to correct your assumptions about how large the cancellation mode value in the buffer is supposed to be, because it's apparently smaller than you expect. Your code assumes it's a uint16_t (2 bytes) but there's only one byte left in the data.
[NSNumber numberWithInt:feedbackCancellationMode]}]
should be
[NSNumber numberWithInteger: feedbackCancellationMode]}]

C General Protection Fault trying to access object in array

In my program, I store objective-c objects in a c array, like this
va_start(list, o);
retval->objs = malloc(SIZE * count);
retval->objs[0] = (__bridge void *)o;
for (int i = 1; i < count; i++)
{
id o = va_arg(list, id);
retval->objs[i] = (__bridge void *)o;
}
va_end(list);
(count is a number containing how many objects will be added; that value is always correct)
objs is a void ** and is part of retval, which is a pointer to a struct. As of now, SIZE is defined as 100. Increasing and decreasing that had no effect.
As you can see, I bridge o to a void *, as I have to. objs, when all the objects are added, contains 3 objective-c objects. When I try to access a value like this
void *obj = CLArrayObjectAtIndex(_arr, ind);
return (__bridge id)obj;
this is the CLArrayObjectAtIndex() function
void *CLArrayObjectAtIndex(CLArrayType *arr, int ind)
{
void *o = arr->objs[ind];
if (o)
return o;
else
perror("Attempt to access NULL object or index out of bounds."), abort();
}
if the index (ind) is 0, it works. If the index is 1, the program crashes when it returns in main. If the index is 2, the program crashes as soon as I try to access it. If the index is 1, the value returned above is correct, but when the program crashes on return it is nil.
If the index is 1, the EXC_BAD_ACCESS code is 1; if the index is 2, the code is EXC_I386_GPFLT, a general protection fault. I already checked here for an explanation of this exception, although I couldn't find anything helpful. So, does anybody see why this error may be occurring?
when you store obj-c objects in C array don't just bridge cast them since that way arc doesn't know they are still used and releases them. __bridge_retain them so they stay around later, when you free the array __bridge_transfer them to give them back to ARC
also don't define size as 100.. sizeof(id) should work. You only need to store pointers

Memory access violation VC++

I'm getting a memory access violation which i am not able to figure out. I am guessing my syntax might be wrong somewhere. Here is my code
load(double **pDouble)
{
int size;
//pStruct is returned by a method of some object inside load
// arr is an array of double, also member of struct pointed by pStruct.
size = sizeof(pStruct->arr)/sizeof(double);
*pDouble = new double[size];
for(int i = 0 ; i < size; i++)
{
*pDouble[i] = pStruct->arr[i];
//the violation occurs for the second iteration of
// the loop
}
}
What could be causing the access violation?
Array indexing binds more tightly than pointer dereferencing. You probably meant:
(*pDouble)[i] = pStruct->arr[i];
There may be other errors though.

Expected expression before 'unsigned' ->Objective C

m_cAppIdMap is an object of a dictionary.
I want to iterate through the dictionary and to ind and remove the value pEvent.wTimerId is an unsigned short integer that is stored as key in the dictionary.
if(unsigned short* key in m_cAppIdMap) //error:Expected expression before 'unsigned'
{
(void)[self findAndRemoveEvent:pEvent];
(void)CFDictionaryRemoveValue(m_cAppIdMap,&wTimerId);
free(pEvent);
bReturn = YES;
}
I am getting an error when i try to iterate through the loop.
EDITED
-(BOOL)KillTimer:(unsigned short)wTimerId
{
stRs232Timer* pEvent;
BOOL bReturn=FALSE;
theLock = [[NSLock alloc]init];
if ([theLock tryLock]) {
// if ( m_cAppIdMap.Lookup(wTimerId,pEvent) )
// {
// (void)findAndRemoveEvent(pEvent); // remove from event queue
// (void)m_cAppIdMap.RemoveKey(wTimerId); // remove from app map
for(wTimerId in m_cAppIdMap)
{
(void)[self findAndRemoveEvent:pEvent];
(void)CFDictionaryRemoveValue(m_cAppIdMap,&wTimerId);
free(pEvent);
bReturn = YES;
}
[theLock unlock];
}
return bReturn;
}
I am getting error in this code 'selector element does not have a valid object type' . I need to search for wTimerId(key) in the m_cAppIdMap. Is it what i'm doing is correct.The commented lines above the for loop is the implementation of the same code in cpp. I coud not make the same logic over here in Objective C.
I think you meant to use for rather than if. Additionally, the fast enumeration syntax
for (x in y) can only be used on objects that implement the NSFastEnumeration protocol—typically NSArray. It looks like you're using C arrays, so this syntax won't work anyway.
you meant to write for (VARIABLE in CONTAINER) {...} -- but your sample uses if, not for.
side note: it is an error to mutate the collections you iterate over during the iteration.

Objective-C Exception Handling: "Divided by Zero Exception" is not getting caught

I have the following code in my program.
#try {
float result = 4 / 0; // LINE 1
} #catch (NSException *e) {
NSLog(#"Exception : %#", e);
return 0;
}
I expected an exception to be caught in LINE 1 and thrown to the #catch block. But the execution aborts at LINE 1 showing EXC_ARITHMETIC in console.
What am I doing wrong here? What necessary things I have to do to do exception handling?
EXC_ARITHMETIC is a type of low-level exception known as a "signal". The only way to catch them is to register a signal handler, for example:
#include<signal.h>
void handler(int signal) {
if (signal == FPE_FLTDIV)
printf("Divide by 0 exception\n");
}
signal(SIGFPE, handler);
However, the only safe thing to do in such a handler is clean up any resources and exit cleanly.
Divide by zero is not an NSException.
Give this a try (I never tried though):
#try {
float result = 4 / 0; // LINE 1
} #catch (NSException *e) {
NSLog(#"Exception : %#", e);
return 0;
}
#catch (id ue) {
//DIVIDE BY ZERO ATTEMPT MAY ENDUP HERE
NSLog(#"Exception : %#", ue);
return 0;
}
====== EDIT =======
Turns out divide by zero is not a obj-c exception. But seems you can catch such exceptions globally.
How do I catch global exceptions?
Exceptions List and division by zero isn't a predefined exception. Also, to know the type of exception, you should send name message to the exception object.
NSLog(#"Exception : %#", [ e name ] );
Actually float result = 4 / 0; would never raise any kind of signal or exception (xcode, LLVM). No idea why it just silently returns inf into result.
"4 / 0" is an expression with known literals, which can be very easily computed by compile time -- therefore there will be no runtime exception on that...
I am using the LLVM 5.1 compiler. In a *.m file just tried the line
float result = 4 / 0;
and
int result = 4 / 0;
and both give the result to be zero. But, because both contain the expression 4 / 0 which is integer division by zero regardless of the variable definition type, the compiler only gives a warning. All other compilers that I have used would have given an error from this expression.
The C language only specifies that integer division by zero is undefined. The compilers used in this case apparently define the result to be zero. This is a good example of why you should never depend on undefined behavior behaving the way you expect.