0

So, I have to add a functionality to an old .cpp file.It's huge. So rewriting it in Objective C is not an option. Instead, I have added the necessary functionality using Objective-C (because I need a lot of the NSDate/NSDateFormatter functions). It worked fine. BUT, when calling the getter (on my view controller) I get this error: EXC_BAD_ACCESS.

Here is a fragment of the code:

//.h file  -----------------
// C/C++ headers
#import <Foundation/NSDate.h>
#import <Foundation/NSDateFormatter.h>

namespace MySpace {
    class Session {
        private:
            // C++ stuff
            NSDate * startTime;
        public:
            // C++ stuff
            NSDate * getStartTime();
            Session(NSDate * startTime );
    };
}

// .cpp file -----------------
using namespace MySpace;
Session:Session (NSDate * startTime) {
    // unrelated code
    if (startTime == nil ){
        startTime = [NSDate date];
    }
    setStartTime( startTime);
    // unrelated code
}

void Session::setStartTime( NSDate * startTime){
    this->startTime = [startTime copy];
}

NSDate * Session::getStartTime() {
    return this->startTime; // here I get the EXC_BAD_ACCESS
}

The entire project is compiled as Objective-C++ and ARC enabled. I believe this issue is caused because the member 'startTime' is released by ARC, and, when I call the getter, it points to nil?

How may I solve this problem?

Thanks.

Lebyrt
  • 1,376
  • 1
  • 9
  • 18
subzero
  • 3,420
  • 5
  • 31
  • 40

1 Answers1

1

Try that:

NSDate * Session::getStartTime() {
    if (this == NULL) return nil;
    return this->startTime; // here I get the EXC_BAD_ACCESS
}

The change makes getStartTime immune to a NULL this pointer.

Does that helps? If so, somewhere, you are using a dangling Session* pointer.

Step 2

Not that. That then:

@interface MyNSDate: NSDate
@end

@implementation MyNSDate

- (id) init
{
    self = [super init];
    if ( self == nil ) return nil;

    NSLog( @"MyNSDate %@ initialized", self );

    return self;
}

- (void) dealloc
{
    // ARC: no super call
    NSLog( @"MyNSDate %@ deallocated", self );
}

@end

And replace the NSDate* in your class with MyNSDate. Check the messages, breakpoint in dealloc... You should be able to find out when the date is deallocated, appropriate or not, or rules out that hypothesis.

The other idea that crossed my mind is the missing copy construcoperators. If you are copying your Session between ARC and non-ARC compilation units, it may break. You shouldn't do that, but hey, it happens.

Session::Session( const Session& rhs )
{
    this->startTime = [rhs.startTime copy];
}

Session& Session::operator=( const Session& rhs )
{
    if ( this->startTime != rhs.startTime )
    {
        this->startTime = [rhs.startTime copy];
    }

    return *this;
}
  • I tried it. Nope, it halts when trying to return this->starTime. Same issue: EXC_BAD_ACCESS – subzero Jun 20 '12 at 22:38
  • Eww. OK then. Adding a little something to my answer. Give it a try. – fabrice truillot de chambrier Jun 20 '12 at 23:20
  • Option 2 was the way to go. Funny fact: there was not any problem around this class, the problem was made by the caller. Someone extended the life of a temporary object and then... it went out of scope, that caused this problem. Here more info: http://stackoverflow.com/questions/2615162/return-value-not-a-reference-from-the-function-bound-to-a-const-reference-in Btw. one question, when is "this" going to be NULL. Line: if (this == NULL) return nil; Thanks – subzero Jul 11 '12 at 21:51
  • Since you had a bad access error, I thought the `Session` pointer was `NULL`, i.e. `Session* session = NULL;` immediately followed with `session->getStartTime();`. In that case, `this` would be `NULL` in `getStartTime`, since `getStartTime` is not virtual. – fabrice truillot de chambrier Jul 12 '12 at 00:25