2

I have a sample project here on github where I created a c++ wrapper class for an external C++ library that I want to use in Objective-C.

I don't understand why my returned pointers are sometimes correct and sometimes wrong. Here's sample output:

Test Data = 43343008
In Compress 43343008
Returned Value = 43343008
Casted Value = 43343008

Test Data = 2239023
In Compress 2239023
Returned Value = 2239023
Casted Value = 2239023

Test Data = 29459973
In Compress 29459973
Returned Value = 29459973
Casted Value = l.remote

Test Data = 64019670
In Compress 64019670
Returned Value = 
Casted Value = stem.syslog.master

In the above output you can see that the 1st and 2nd click of the button outputs the results I was expecting. In each of the other clicks either the returned value or casted value are invalid. I'm assuming this is because my pointer is pointing to an address I wasn't expecting. when running the app multiple times, any button click could be right or wrong.

I also tried with a single thread but experienced similar results.

The complete code is on github but here are the important bits.

ViewController.m

#import "ViewController.h"

extern const char * CompressCodeData(const char * strToCompress);

@implementation ViewController

...

// IBAction on the button
- (IBAction)testNow:(id)sender 
{
    [self performSelectorInBackground:@selector(analyze) withObject:nil];
}

- (void)analyze
{
    @synchronized(self) {

        const char *testData = [[NSString stringWithFormat:@"%d", 
                      (int)(arc4random() % 100000000)] UTF8String];
        NSLog(@"Test Data = %s", testData);

        const char *compressed = CompressCodeData(testData);
        NSLog(@"Returned Value = %s", compressed);

        NSString *casted = [NSString stringWithCString:compressed
                                          encoding:NSASCIIStringEncoding];
        NSLog(@"Casted Value = %@\n\n", casted);

    }
}

@end

SampleWrapper.cpp

#include <iostream>
#include <string.h>
#include <CoreFoundation/CoreFoundation.h>

using namespace std;

extern "C" 
{
    extern void NSLog(CFStringRef format, ...); 

    /**
     * This function simply wraps a library function so that 
     * it can be used in objective-c.
     */
    const char * CompressCodeData(const char * strToCompress) 
    {
        const string s(strToCompress);

        // Omitted call to static method in c++ library
        // to simplify this test case.

        //const char *result = SomeStaticLibraryFunction(s);
        const char *result = s.c_str();

        NSLog(CFSTR("In Compress %s"), result);
        return result;
    }

}

1 Answer 1

4

You are returning a pointer to at object that has been deallocated.

const string s(strToCompress);
…
const char *result = s.c_str();

NSLog(CFSTR("In Compress %s"), result);
return result;

s does not exist after CompressCodeData() function is over, so the pointer to it's internal memory is invalid.


You could allocate a chunk of memory to hold the response, but it would be up to the caller to release it.

char *compressed = CompressCodeData(testData);
NSLog(@"Returned Value = %s", compressed);

NSString *casted = [NSString stringWithCString:compressed
                                      encoding:NSASCIIStringEncoding];
free(compressed);
NSLog(@"Casted Value = %@\n\n", casted);

…

const char * CompressCodeData(const char * strToCompress)
…
char *result = strdup(s.c_str());

Another solution is to pass in the memory to store the data into.

char compressed[2048]; // Or whatever!
CompressCodeData(testData, compressed, sizeof(compressed));
NSLog(@"Returned Value = %s", compressed);

NSString *casted = [NSString stringWithCString:compressed
                                      encoding:NSASCIIStringEncoding];
NSLog(@"Casted Value = %@\n\n", casted);

…

void CompressCodeData(const char * strToCompress, char *result, size_t size)
…
s.copy(result, size - 1);
result[s.length() < size ? s.length() : size-1] = '\0';
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.