There's a memory leak in my program and because I'm not well versed in C (created a function in my Objective-C class to load strings from a SQLite database). Can anyone spot my blunder? Thank you:
static int MyCallback(void *context, int lCount, char **values, char **columns){
NSMutableArray *sqlRawStrings = (NSMutableArray *)context;
for (int i = 0; i < lCount; i++) {
const char *nameCString = values[i];
if (nameCString != NULL) {
[sqlRawStrings addObject:[NSString stringWithUTF8String:nameCString]];
}
}
return SQLITE_OK;
}
All this is called earlier here:
int numberA = [loadBundleNumber intValue];
char str1[130] = "select ";
for(int i = 7; i <7 + numberA; i++){
str1[i] = 'a';
}
char str2[20] = " from puzzles";
strcat(str1,str2);
NSString *file = [[NSBundle mainBundle] pathForResource:#"finalPuzzles" ofType:#"db"];
sqlite3 *database = NULL;
if (sqlite3_open([file UTF8String],&database) == SQLITE_OK) {
sqlite3_exec(database, str1, MyCallback, sqlRawStrings, NULL);
}
sqlite3_close(database);
Thanks
More comments than answers as I don't see how you're leaking memory just yet (not enough points to comment yet). How are you observing that there is a memory leak? Can you see what's inside the object that is being leaked and work back through its allocation stack trace to see what it is?
Also can you supply the declaration for sqlRawStrings?
As an aside, I think that the way you're building your strings could be improved. Consider using sprintf. You might also want to consider using a .mm file instead of .m and then you'll get C++ capability; the std::string class could help you.
Finally, do not close something unless you've successfully opened it i.e. the "sqlite3_close" should be within the same block as sqlite3_exec.
'hope that this is helpful.
Best guess is that sqlRawStrings is never released and so neither is anything added to it.
Related
I know I can loop through each character of two NSString objects using characterAtIndex: and compare them, but this approach would be very expensive if I use this function frequently.
Is there anything built in for this, or a more efficient way to do it?
The quickest way i can think of is to get a C string from it, and then iterate through the strings.
Just a quick example (fix it to your liking):
const char* myCString = [myNSStringInstance UTF8String];
const char* string2 = [nsstring2 UTF8String];
// Assume same length. You can fix this
for(i = 0; i < strlen(myCString); i++) {
if(myCString[i] != string2[i]) {
// Do something here...
}
}
It's a litte hackish, but you could get the c-string for each and then use pointer indexing. Same basic algorithm as your mentioned idea, but theoretically as efficient as you could reasonably expect a solution to be (just looking at two memory addresses and comparing their contents.
Pseudo code:
char *stringA = [stringA cStringUsingEncoding:NSUTF8StringEncoding];
char *stringB = [stringB cStringUsingEncoding:NSUTF8StringEncoding];
int mismatchIndex = -1;
for(int i = 0; i<shorterStringLength; i++) {
if (stringA[i] != stringB[i]) {
mismatchIndex = i;
break;
}
}
I've got a c-array of CGPoints in a struct. I need to replace this array when another CGPoint is added. I'd swear I'm doing this right and it seems to work fine a few times but eventually I'll get a EXC_BAD_ACCESS. What am I missing?
Here's the struct, which I've truncated to remove a lot of items that don't pertain.
typedef struct{
CGPoint **focalPoints;
NSUInteger focalPointCount;
CGRect boundingRect;
}FocalPoints;
Here's how I initialize it:
CGPoint *fPoints = (CGPoint *)malloc(sizeof(CGPoint));
FocalPoints focalInfo = {&fPoints, 0, rect};
Note that focalInfo is passed by reference to another function, like so: anotherFunction(&focalInfo).
Now here's the function that replaces the Points array with a new one:
void AddFocalPoint (CGPoint focalPoint, FocalPoints *focal){
if (focalPoint.x == CGFLOAT_MAX) return;
if (!CGRectContainsPoint(focal->boundingRect, focalPoint)) return;
int origCount = focal->focalPointCount;
int newCount = origCount + 1;
CGPoint *newPoints = (CGPoint *) malloc((newCount) * sizeof(CGPoint));
for (int i = 0; i < newCount; i++)
newPoints[i] = (i < origCount) ? *focal->focalPoints[i] : focalPoint; //error occurs here
free(*focal->focalPoints);
*focal->focalPoints = newPoints;
focal->focalPointCount = newCount;
}
The EXC_BAD_ACCESS error occurs in the above code on line 8: newPoints[i] = (i < origCount) ? *focal->focalPoints[i] : focalPoint;. So what exactly am I doing wrong?
This is a bit of a long shot, but maybe there's an issue with operator priority in *focal->focalPoints[i]. Have you try adding parentheses according to what you are trying to achieve ?
I believe the issue comes with where GCPoint *fPoints allocated as &fPoints evaluates to an address of that ... which is no longer valid once the function exits.
(The data to which it points was allocated fine with malloc.)
Aside from the suggestion I made in a comment, of using a linked list/NSMutableArray, my other suggestion would be that you use realloc() instead of constantly using malloc(), copying by hand, and then free()ing the old allocation.
void * realloc(void *ptr, size_t size);
The realloc() function tries to change the size of the allocation pointed to by ptr to size, and returns ptr. If there is not enough room to enlarge the memory allocation pointed to by ptr, realloc() creates a new allocation, copies as much of the old data pointed to by ptr as will fit to the new allocation, frees the old allocation, and returns a pointer to the allocated memory.
This is pretty much exactly what you are doing, but you can let the library handle it for you.
(May I also humbly suggest using the word "focal" slightly less to name variables in your function?) (Also also, I'm not really clear on why focalPoints in your struct is a pointer-to-pointer. You just want an array of structs -- a single pointer should be fine.)
Consider the following (somewhat extensive) rewrite; hope that it's helpful in some way.
typedef struct{
CGPoint *points; // Single pointer
NSUInteger count;
CGRect boundingRect;
} FocalPoints;
// Renamed to match Apple's style, like e.g. CGRectIntersectsRect()
void FocalPointsAddPoint (FocalPoints *, CGPoint);
void FocalPointsAddPoint (FocalPoints *f, CGPoint thePoint){
if (thePoint.x == CGFLOAT_MAX) return;
if (!CGRectContainsPoint(f->boundingRect, thePoint)) return;
NSUInteger origCount = f->count; // |count| is typed as NSUInteger; |origCount|
NSUInteger newCount = origCount + 1; // and |newCount| should be consistent
// Greatly simplified by using realloc()
f->points = (CGPoint *) realloc(f->points, newCount * sizeof(CGPoint));
(f->points)[newCount-1] = thePoint;
f->count = newCount;
}
int main(int argc, const char * argv[])
{
#autoreleasepool {
// Just for testing; any point should be inside this rect
CGRect maxRect = CGRectMake(0, 0, CGFLOAT_MAX, CGFLOAT_MAX);
// Can initialize |points| to NULL; both realloc() and free() know what to do
FocalPoints fp = (FocalPoints){NULL, 0, maxRect};
int i;
for( i = 0; i < 10; i++ ){
FocalPointsAddPoint(&fp, CGPointMake(arc4random() % 100, arc4random() % 100));
NSLog(#"%#", NSStringFromPoint(fp.points[i]));
}
}
return 0;
}
It's possible to get list of classes from a bundle via NSBundleDidLoadNotification. But I can't figure out how I can get them from already loaded bundle. (same bundle with code)
I'm trying to get class list of my application bundle. More specifically, the classes only in my application binary.
I looked at objc_getClassList, but it returns ALL classes and it's obviously too heavy for me. I need lightweight method. I found objc_copyClassNamesForImage by googling, but it's not documented, and I don't know how to use it safely. I think I can try to use it conventionally, but I want to find another more safe option before going there.
Another option would be to iterate through all the classes registered with the runtime and use +[NSBundle bundleForClass:] on each one to figure out which one it came from. You can then sort things into sets based on the result.
Something like this:
#interface NSBundle (DDAdditions)
- (NSArray *)definedClasses_dd;
#end
#implementation NSBundle (DDAdditions)
- (NSArray *)definedClasses_dd {
NSMutableArray *array = [NSMutableArray array];
int numberOfClasses = objc_getClassList(NULL, 0);
Class *classes = calloc(sizeof(Class), numberOfClasses);
numberOfClasses = objc_getClassList(classes, numberOfClasses);
for (int i = 0; i < numberOfClasses; ++i) {
Class c = classes[i];
if ([NSBundle bundleForClass:c] == self) {
[array addObject:c];
}
}
free(classes);
return array;
}
#end
Then you can call:
NSLog(#"%#", [[NSBundle mainBundle] definedClasses_dd]);
Try this magic:
- (NSArray *)getClassNames {
NSMutableArray *classNames = [NSMutableArray array];
unsigned int count = 0;
const char **classes = objc_copyClassNamesForImage([[[NSBundle mainBundle] executablePath] UTF8String], &count);
for(unsigned int i=0;i<count;i++){
NSString *className = [NSString stringWithUTF8String:classes[i]];
[classNames addObject:className];
}
return classNames;
}
I could find some example for the function objc_copyClassNamesForImage at here.
http://www.opensource.apple.com/source/objc4/objc4-493.9/test/weak.m
// class name list
const char *image = class_getImageName(objc_getClass("NotMissingRoot"));
testassert(image);
const char **names = objc_copyClassNamesForImage(image, NULL);
testassert(names);
testassert(classInNameList(names, "NotMissingRoot"));
testassert(classInNameList(names, "NotMissingSuper"));
if (weakMissing) {
testassert(! classInNameList(names, "MissingRoot"));
testassert(! classInNameList(names, "MissingSuper"));
} else {
testassert(classInNameList(names, "MissingRoot"));
testassert(classInNameList(names, "MissingSuper"));
}
free(names);
The source code is unofficial but from Apple. So I decided to use this code until I find any better way.
Say I have my class
#interface Person : NSObject { NSString *name; }
I need to get the name of NSString's within my class
Person *person = [[Person alloc] init];
NSLog(#"Name of variable %s\n", _NameofVariable_(person->name));
Thanks for the answers, here's the solution I came up from the replies
//returns nil if property is not found
-(NSString *)propertyName:(id)property {
unsigned int numIvars = 0;
NSString *key=nil;
Ivar * ivars = class_copyIvarList([self class], &numIvars);
for(int i = 0; i < numIvars; i++) {
Ivar thisIvar = ivars[i];
if ((object_getIvar(self, thisIvar) == property)) {
key = [NSString stringWithUTF8String:ivar_getName(thisIvar)];
break;
}
}
free(ivars);
return key;
}
As easy as
#define VariableName(arg) (#""#arg)
Then you do:
NSObject *obj;
NSString *str = VariableName(obj);
NSLog(#"STR %#", str);//obj
You can get the names of a class's instance variables with the Objective-C runtime API function class_copyIvarList. However, this is rather involved, rarely done and almost never the best way to accomplish something. If you have a more specific goal in mind than mere curiosity, it might be a good idea to ask about how to accomplish it in Objective-C.
Also, incidentally, person.name doesn't specify an instance variable in Objective-C — it's a property call. The instance variable would be person->name.
You might use preprocessor stringification and a bit of string twiddling:
NSUInteger lastIndexAfter(NSUInteger start, NSString *sub, NSString *str) {
NSRange found = [str rangeOfString:sub options:NSBackwardsSearch];
if(found.location != NSNotFound) {
NSUInteger newStart = NSMaxRange(found);
if(newStart > start)
return newStart;
}
return start;
}
NSString *lastMember(NSString *fullName) {
if(!fullName) return nil;
NSUInteger start = 0;
start = lastIndexAfter(start, #".", fullName);
start = lastIndexAfter(start, #"->", fullName);
return [fullName substringFromIndex: start];
}
#define NSStringify(v) (##v)
#define _NameofVariable_(v) lastMember(NSStringify(v))
If the person object is exposed as a property of the class, you can use objc_msgSend to get the value.
So, if you could access person using
[object person]
You could also do
objc_msgSend(object, "person")
For more details on message sending, including how to pass arguments to methods, see the Objective-C Runtime Programming Guide section on Messaging
The following works as a macro:
#define STRINGIZE(x) #x
I'm attempting conversion of a legacy C++ program to objective-C. The program needs an array of the 256 possible ASCII characters (8-bits per character). I'm attempting to use the NSString method initWithBytes:length:encoding: to do so. Unfortunately, when coded as shown below, it crashes (although it compiles).
NSString* charasstring[256];
unsigned char char00;
int temp00;
for (temp00 = 0; temp00 <= 255; ++temp00)
{
char00 = (unsigned char)temp00;
[charasstring[temp00] initWithBytes:&char00 length:1 encoding:NSASCIIStringEncoding];
}
What I'm missing?
First, the method is simply initWithBytes:length:encoding and not the NSString::initWithBytes you used in the title. I point this out only because forgetting everything you know from C++ is your first step towards success with Objective-C. ;)
Secondly, your code demonstrates that you don't understand Objective-C or use of the Foundation APIs.
you aren't allocating instances of NSString anywhere
you declared an array of 256 NSString instance pointers, probably not what you want
a properly encoded ASCII string does not include all of the bytes
I would suggest you start here.
To solve that specific problem, the following code should do the trick:
NSMutableArray* ASCIIChars = [NSMutableArray arrayWithCapacity:256];
int i;
for (i = 0; i <= 255; ++i)
{
[ASCIIChars addObject:[NSString stringWithFormat:#"%c", (unsigned char)i]];
}
To be used, later on, as follows:
NSString* oneChar = [ASCIIChars objectAtIndex:32]; // for example
However, if all you need is an array of characters, you can just use a simple C array of characters:
unsigned char ASCIIChars [256];
int i;
for (i = 0; i <= 255; ++i)
{
ASCIIChars[i] = (unsigned char)i;
}
To be used, later on, as follows:
unsigned char c = ASCIIChars[32];
The choice will depend on how you want to use that array of characters.