Register FAQ / Rules Forum Spy Search Today's Posts Mark Forums Read
Go Back   MacRumors Forums > Apple Systems and Services > Programming > iPhone/iPad Programming

Reply
 
Thread Tools Search this Thread Display Modes
Old Jul 16, 2010, 08:19 AM   #1
xelhark
macrumors newbie
 
Join Date: Jul 2010
Variable Passing issue

Hi there!

I was working on a Sudoku Generator. While trying different approaches i tried to create a Tree in which every node contains a partial generation, and if it can't go on that node is bounded. Eventually it should find a solution.

The algorithm is not the problem, just take a look at this!


Code:
-(void) solve{
	ConstraintGraph *g = [[ConstraintGraph alloc] initAsSudoku];
	
	SolutionTree *tree = [[SolutionTree alloc] init];

	tree.root->info = (Node*)(g.nodeList->Head->info);
	
	tree.root->info->n = 3;
	NSLog(@"the value is %d", tree.root->info->n);
 * * * *//this prints 'the value is 3'
	[self visitNode:tree.root];
	
}

-(void) visitNode:(solutionTreeNode*)N{
 * * * *//this prints 'the value is 1296' (or another number)
	NSLog(@"he value is %d", N->info->n);
}

The first NSLog prints
Code:
the value is 3
the second one (in visitNode) prints:

Code:
the value is 1456
or other random numbers..

I think the problem happens when i pass the variable, but i couldn't figure it out. Could you please help me?

Thanks in advance
xelhark is offline   0 Reply With Quote
Old Jul 16, 2010, 08:54 AM   #2
PhoneyDeveloper
macrumors 68030
 
PhoneyDeveloper's Avatar
 
Join Date: Sep 2008
Are there any warnings when you compile this? Are all the declarations in scope?

Otherwise it's difficult to guess without seeing the declarations for all the relevant bits. I'll also say it's a bit weird to see the -> operator mixed with Objective-C classes, but legit if you know what you're doing.
PhoneyDeveloper is online now   0 Reply With Quote
Old Jul 16, 2010, 11:11 AM   #3
xelhark
Thread Starter
macrumors newbie
 
Join Date: Jul 2010
Quote:
Are there any warnings when you compile this? Are all the declarations in scope?
Nope, no warning, nothing at all..

Quote:
Otherwise it's difficult to guess without seeing the declarations for all the relevant bits. I'll also say it's a bit weird to see the -> operator mixed with Objective-C classes, but legit if you know what you're doing.
Actually i'm using Objective-C++ which lets me use structs and lists rather than NSMutableArrays (i'm trying to make it as fast as i can), and that's why i'm using -> operator

anyway, i tried to take a better look at it, and it might be some casting problem..

I isolated it here..
Code:
	ConstraintGraph *g = [[ConstraintGraph alloc] initAsSudoku];
	NSLog(@"The value is %d", ((Node*)(g.nodeList->Head->info))->n);
The ConstraintGraph is a graph in which a node is connected to another node if they must have different values. (for example, a node is connected with all of the other nodes in his row, column and 3x3 subgrid)


anyway, the NSLog here prints
'The value is [random number]'

This is the code from the 'initAsSudoku' method.

Code:
-(id) initAsSudoku{
	if ((self = [super init])) {
		Node Nodi[SUDOKUSIZE][SUDOKUSIZE];
		for (int i=0; i<SUDOKUSIZE; i++) {
			for (int j=0; j<SUDOKUSIZE; j++) {
				Nodi[i][j].Adjs = new myList();
				//-----------------HERE I AM INITIALIZING THE n AS 0
				Nodi[i][j].n = 0;
			}
		}	
		
		/*
		 You can skip this part, it just creates the connections
		 */
		for (int i=0; i<SUDOKUSIZE; i++) {
			for (int j=0; j<SUDOKUSIZE; j++) {
				//Adding Constraints...
				//The first SUDOKUSIZE-1 (except itself) are the ones from its subgrid
				for (int k=0; k<SUDOKUSIZE; k++) {
					int x = (((i/sizeX)*sizeX)+(k%3));
					int y = (((j/sizeY)*sizeY)+(k/3));
					if (x!=i || y != j) {
						Nodi[i][j].Adjs->addNodeContaining(&Nodi[x][y]);
					}
				}
				//The others are from its row/column (except the ones in the subgrid)
				for (int k=0; k<SUDOKUSIZE; k++) {
					if (k/sizeX != i/sizeX) {
						Nodi[i][j].Adjs->addNodeContaining(&Nodi[k][j]);
					}
					if (k/sizeY != j/sizeY) {
						Nodi[i][j].Adjs->addNodeContaining(&Nodi[i][k]);
					}
				}
			}
		}
		/*
		 Here all connections are created, i store the nodes in a list then return
		 */
		nodeList = new myList();
		//Adding nodes in the list..
		for (int i=0; i<SUDOKUSIZE; i++) {
			for (int j=0; j<SUDOKUSIZE; j++) {
				nodeList->addNodeContaining(&Nodi[i][j]);
			}
		}
		NSLog(@"The value is %d", ((Node*)(self.nodeList->Head->info))->n);
	}
	return self;
}
The list holds a (void*) as info, that's why i need the cast.

The weird thing is, the NSLog here prints '0' (the right value). Once the code returns to the first method, the VERY SAME instruction prints another value (random)

i don't know what to do please help
xelhark is offline   0 Reply With Quote
Old Jul 16, 2010, 12:03 PM   #4
PhoneyDeveloper
macrumors 68030
 
PhoneyDeveloper's Avatar
 
Join Date: Sep 2008
Remember that NSLog is a varargs method and it doesn't really know the types of the values passed to it. You can put a typecast in the NSLog to help it with the type, like:

Code:
NSLog(@"The value is %d", (int)((Node*)(g.nodeList->Head->info))->n);
Otherwise what happens with something like

Code:
NSInteger d = (g.nodeList->Head->info)->n;
NSLog(@"The value is %d", d);
PhoneyDeveloper is online now   0 Reply With Quote
Old Jul 16, 2010, 12:46 PM   #5
chown33
macrumors 603
 
Join Date: Aug 2009
Quote:
Originally Posted by xelhark View Post
Code:
		/*
		 Here all connections are created, i store the nodes in a list then return
		 */
		nodeList = new myList();
		//Adding nodes in the list..
		for (int i=0; i<SUDOKUSIZE; i++) {
			for (int j=0; j<SUDOKUSIZE; j++) {
				nodeList->addNodeContaining(&Nodi[i][j]);
			}
		}
		NSLog(@"The value is %d", ((Node*)(self.nodeList->Head->info))->n);
	}
	return self;
}
First, you need to post the datatypes: struct definitions, class headers, properties, etc. We can't tell what anything is except by guessing from context. There isn't enough context to determine what's really happening.

Second, assuming that nodeList is both an ivar and a property, you are accessing the property in two different ways (red hilited code). This may be a problem if your property is defined as retain, but you don't consistently use the property accessors.

So my guess is that you somehow have a variable being deleted or dealloc'ed, yet you still have a reference to it, but without seeing more of the data types and properties, it's just a guess.


In general, the debugging strategy to use is Bracketing. You set a breakpoint before or at the initFunction. You inspect the variables. You set another breakpoint at the end of the function. Inspect variables again. Set a third breakpoint right before the printing that doesn't work. Inspect variables yet again, and then single-step only if they're correct.

If all the variables (and the memory they point to) is always correct, and the print works, then expand the range bracketed by the breakpoints. If the 2nd or 3rd breakpoint shows incorrect variables (or memory), then move the breakpoint earlier or later, so there are always 2 breakpoints bracketing a suspected section of code. You will eventually find the statement that's wrong as you move the breakpoint past it.

You can move the 1st breakpoint later, as you find that a bracketed section of code is correct. The 1st breakpoint establishes your "known good" state. The other 2 move as you search for the point at which it goes bad.
chown33 is offline   0 Reply With Quote
Old Jul 16, 2010, 03:55 PM   #6
jared_kipe
macrumors 68030
 
jared_kipe's Avatar
 
Join Date: Dec 2003
Location: Seattle
Send a message via AIM to jared_kipe
Quote:
Originally Posted by xelhark View Post
Nope, no warning, nothing at all..


Actually i'm using Objective-C++ which lets me use structs and lists rather than NSMutableArrays (i'm trying to make it as fast as i can), and that's why i'm using -> operator
Are you kidding? Do you know how powerful the iPhone is when compared to the small differences in speed between C++ and Obj-C messaging?

Smells like premature optimization to me.
jared_kipe is offline   0 Reply With Quote
Old Jul 17, 2010, 04:49 AM   #7
xelhark
Thread Starter
macrumors newbie
 
Join Date: Jul 2010
Quote:
Originally Posted by chown33 View Post
First, you need to post the datatypes: struct definitions, class headers, properties, etc. We can't tell what anything is except by guessing from context. There isn't enough context to determine what's really happening.

Second, assuming that nodeList is both an ivar and a property, you are accessing the property in two different ways (red hilited code). This may be a problem if your property is defined as retain, but you don't consistently use the property accessors.

So my guess is that you somehow have a variable being deleted or dealloc'ed, yet you still have a reference to it, but without seeing more of the data types and properties, it's just a guess.


In general, the debugging strategy to use is Bracketing. You set a breakpoint before or at the initFunction. You inspect the variables. You set another breakpoint at the end of the function. Inspect variables again. Set a third breakpoint right before the printing that doesn't work. Inspect variables yet again, and then single-step only if they're correct.

If all the variables (and the memory they point to) is always correct, and the print works, then expand the range bracketed by the breakpoints. If the 2nd or 3rd breakpoint shows incorrect variables (or memory), then move the breakpoint earlier or later, so there are always 2 breakpoints bracketing a suspected section of code. You will eventually find the statement that's wrong as you move the breakpoint past it.

You can move the 1st breakpoint later, as you find that a bracketed section of code is correct. The 1st breakpoint establishes your "known good" state. The other 2 move as you search for the point at which it goes bad.
Uhm... You're right, i didn't think of it, i'll check it out and let you know.. Thanks a lot



Quote:
Originally Posted by jared_kipe View Post
Are you kidding? Do you know how powerful the iPhone is when compared to the small differences in speed between C++ and Obj-C messaging?

Smells like premature optimization to me.
Actually, i once tried using a NSMutableArray for things like that, and it came up being really really slow compared to this kind of lists, but maybe there were other things slowing it down.. I'm not sure, and i'm pretty new to Objective-C and iPhone programming, so if you think it's faster to use NSMutableArrays instead of lists i'd be glad to accept your advice
xelhark is offline   0 Reply With Quote
Old Jul 17, 2010, 05:03 AM   #8
xelhark
Thread Starter
macrumors newbie
 
Join Date: Jul 2010
GREEEEEEEEAT!!

thanks a lot chown33, you spotted the precise problem!

The problem was, i was allocating the nodes in the stack and not in the heap, so even if i saved them in the "nodeList" they were being deleted as soon as the function returned.

This was the problem:
Code:
		Node Nodi[SUDOKUSIZE][SUDOKUSIZE]; //<--- STACK ALLOCATION!
		for (int i=0; i<SUDOKUSIZE; i++) {
			for (int j=0; j<SUDOKUSIZE; j++) {
				Nodi[i][j].Adjs = new myList();
				Nodi[i][j].n = 0;
			}
		}
And this is how i solved it:

Code:
		Node **Nodi = (Node**)malloc(SUDOKUSIZE * sizeof(Node*)); //<-- HEAP ALLOCATION
		for (int i=0; i<SUDOKUSIZE; i++) {
			Nodi[i] = (Node*)malloc(SUDOKUSIZE * sizeof(Node)); //Other Heap allocation
			for (int j=0; j<SUDOKUSIZE; j++) {
				Nodi[i][j].Adjs = new myList();
				Nodi[i][j].n = 0;
			}
		}
Thanks to you all guys, you're amazing
xelhark is offline   0 Reply With Quote
Old Jul 17, 2010, 12:23 PM   #9
chown33
macrumors 603
 
Join Date: Aug 2009
Quote:
Originally Posted by xelhark View Post
Actually, i once tried using a NSMutableArray for things like that, and it came up being really really slow compared to this kind of lists, but maybe there were other things slowing it down.. I'm not sure, and i'm pretty new to Objective-C and iPhone programming, so if you think it's faster to use NSMutableArrays instead of lists i'd be glad to accept your advice
You haven't shown any data types. No one can tell whether NSMutableArray is good, when they haven't seen the structure of the data.

And you should realize that Objective-C is a true superset of C. Anything you can do in C, you can also do in Objective-C. This means you can use C arrays, including ones allocated by malloc() or calloc(). You can also use macros.
chown33 is offline   0 Reply With Quote

Reply
MacRumors Forums > Apple Systems and Services > Programming > iPhone/iPad Programming

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Similar Threads
thread Thread Starter Forum Replies Last Post
Who here is passing on the 5s and waiting for the 6? Seņor iPhone 77 Dec 16, 2013 04:09 AM
Having an issue passing data between views with Core Data. iJustinCabral iPhone/iPad Programming 0 Jul 15, 2013 09:50 PM
Trouble Passing Array to Another VC bkm iPhone/iPad Programming 8 Apr 19, 2013 04:48 PM
Passing Data Between Segue w3tmb iPhone/iPad Programming 1 Feb 10, 2013 12:57 PM
For those passing on iPhone 5... TG1 Alternatives to iOS and iOS Devices 60 Sep 13, 2012 10:36 AM

Forum Jump

All times are GMT -5. The time now is 05:26 PM.

Mac Rumors | Mac | iPhone | iPhone Game Reviews | iPhone Apps

Mobile Version | Fixed | Fluid | Fluid HD
Copyright 2002-2013, MacRumors.com, LLC