Why does my program run?

  • (3 Pages)
  • +
  • 1
  • 2
  • 3

30 Replies - 3059 Views - Last Post: 21 August 2012 - 07:14 PM Rate Topic: -----

#1 nullcoding  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 99
  • Joined: 08-July 12

Why does my program run?

Posted 20 August 2012 - 07:50 AM

Yes, the title is a bit odd. Well I have this application I wrote in VC++ (Win32) and it performs a fairly intensive execution when a button is pressed.

It's meant to update the status bar as it cycles through numbers (it's doing math). When I run this program through the debugger in Visual Studio 2010, it runs perfectly. By that, I mean it's smooth and predictable and does what it ought to.

But when I open the executable itself, it locks up at a certain point, says it's not responding, and I need to kill it.

Clearly the debugger is not throwing any exceptions, because as I said, it runs smoothly through that (but only through that).

Why would this happen?

Is This A Good Question/Topic? 0
  • +

Replies To: Why does my program run?

#2 aresh  Icon User is offline

  • It's a 16-Bit World!
  • member icon

Reputation: 273
  • View blog
  • Posts: 4,176
  • Joined: 08-January 12

Re: Why does my program run?

Posted 20 August 2012 - 07:53 AM

Maybe if you can post your code, we can help... And this may be an example of undefined behavior. It runs perfectly once, but crashes the next time you run it.
Was This Post Helpful? 0
  • +
  • -

#3 vividexstance  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 678
  • View blog
  • Posts: 2,330
  • Joined: 31-December 10

Re: Why does my program run?

Posted 20 August 2012 - 08:23 AM

Sometimes the code can run fine in the debugger because you stop the execution at certain points, but when the program just runs normally it can lock up. Without setting any breakpoints, and just running the program through the debugger, it possibly could lock up in the debugger as well.
Was This Post Helpful? 0
  • +
  • -

#4 nullcoding  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 99
  • Joined: 08-July 12

Re: Why does my program run?

Posted 20 August 2012 - 08:32 AM

The thing is, I don't stop execution. I have a disabled breakpoint I was using to check a string's initialization at one point but that's fixed now.

I'm still editing this code, but here's what happens when the button is clicked.

		case IDC_BUTTON3: // when Calculate Proth! is pressed

				if(wmEvent == BN_CLICKED) // when it's clicked, calculate Proth number!!
			{								
				HWND ProthProgress = GetDlgItem(pWnd, IDC_PROTHPROG);
				HWND hStatus = GetDlgItem(pWnd, IDC_MAIN_STATUS);

				int ticks = clock();

					SetDlgItemText(pWnd, IDC_PROTH, L"");
					SetDlgItemText(pWnd, IDC_FACTORS, L"");
					SetDlgItemText(pWnd, IDC_ISPRIME, L"");
					SetDlgItemText(pWnd, IDC_BIGNUM, L"");
					SetDlgItemText(pWnd, IDC_OTHERF, L"");

			SendMessage(hStatus, SB_SETTEXT, 0 | 0, 
				LPARAM (TEXT("Working...")));
			Sleep(50);

				mpz_t c, k, two, rawproth, proth, ZERO, ONE; //sets mpz_t variables without initializing	
				mpz_init (rawproth); //this is essentially proth - 1
				mpz_init (proth);
				mpz_init (c);
				mpz_init_set_ui (ZERO, 0); // ZERO and ONE are used for evaluating mpz_t comparisons instead of ULs.
				mpz_init_set_ui (ONE, 1);
				mpz_init_set_ui (two, 2); 
				unsigned long int one = 1; //this is a surprisingly useful number

				int base = 10; //we use base-10 to determine digits just for fun. And string length.
				
				unsigned long int n = GetDlgItemInt(pWnd, IDC_ENTER_N, write, FALSE); //gets n

				unsigned long int kinput = GetDlgItemInt(pWnd, IDC_ENTER_K, write, FALSE);	//gets k	
			
				if (kinput%2 == 0)
				{
					MessageBox(NULL, L"k must be a positive, odd integer!", L"Bad k", MB_IConerror);
					break;
				}

				mpz_init_set_ui ( k, kinput); //sets mpz_t k from ul kinput
				mpz_pow_ui ( c, two, n); // sets c to 2^n
				mpz_mul ( rawproth, k, c);		   // sets rawproth = k * c
				mpz_add ( proth, rawproth, ONE); // adds 1, creating Proth number!

				/*at this point we have rawproth = k * 2 ^ n; rawproth - 1 = proth :)/>*/				
				int range = n*n;
				SendMessage(ProthProgress, PBM_SETRANGE, NULL, MAKELPARAM(0, range));
				SendMessage(ProthProgress, PBM_SETSTEP, (WPARAM)5, NULL);
				SendMessage(ProthProgress, PBM_STEPIT, NULL, NULL);
				Sleep(350);

				WCHAR szK[32]; // THIS prints the FORMULA to the Proth box.
				swprintf(szK, 32, L"%lu  2^ %lu +1", kinput, n);
				
				SetDlgItemText(pWnd, IDC_PROTH, szK);				
				Sleep(100);
				unsigned long int DIGITS = mpz_sizeinbase (proth, base);

				WCHAR szdig[64]; 				
				swprintf(szdig, 64, L"Proth number with %lu digits generated!", DIGITS);
				
				SetDlgItemText(pWnd, IDC_DIGITS, szdig);
				ZeroMemory(szdig, 64);
				SendMessage(ProthProgress, PBM_STEPIT, NULL, NULL);
				Sleep(100);

				int len = mpz_sizeinbase (proth, base) +2;			//prints Proth # to box!
				char * bigstr = new char[len];						//Thanks Skydiver (D.I.C)
				mpz_get_str (bigstr, base, proth);
				#ifdef UNICODE
				WCHAR * BIGw = new WCHAR[len];
				mbstowcs(BIGw, bigstr, len);
				SetDlgItemText(pWnd, IDC_BIGNUM, BIGw);
				delete [] BIGw;
				#else
				SetDlgItemText(pWnd, IDC_BIGNUM, bigstr);
				#endif
				delete [] bigstr, BIGw;
			
				mpz_clear(k);
				mpz_clear(c);
				mpz_clear(rawproth);
				
				//the Proth number is calculated. Time to test it. 

				mpz_t squareroot, rawroot;
				mpz_init (squareroot);
				mpz_init (rawroot);
				unsigned long int trial=2;

				mpz_sqrt(rawroot, proth);
				mpz_add(squareroot, rawroot, ONE);
				int rootlen = mpz_sizeinbase(squareroot,base) + 75;

				char* TheRootIs = new char[rootlen*2];
				wchar_t* sayroot = new wchar_t[rootlen*2];
				wchar_t* beroot = new wchar_t[rootlen*2];
				mpz_get_str(TheRootIs, base, squareroot);
				mbstowcs(beroot,TheRootIs,rootlen*2);
				swprintf(sayroot, rootlen*2, L"Square Root: %ls", beroot);
				SendMessage(hStatus, SB_SETTEXT, 2 | 0, (LPARAM) sayroot);
				Sleep(25);
				SendMessage(ProthProgress, PBM_STEPIT, NULL, NULL);
				delete [] TheRootIs, sayroot, beroot;

				for (trial=2; mpz_cmp_ui(proth, trial) > 0; trial++)

				{
				mpz_t remainder, quotient;
				mpz_init (remainder);
				mpz_init (quotient);
				float elapsed = clock() - ticks;

					mpz_fdiv_r_ui (remainder, proth, trial); //divides proth by trial and stores remainder in, well, remainder		
					Sleep(10);

					WCHAR* currenttest = new WCHAR[256];
					WCHAR* currenttime = new WCHAR[256];
					swprintf(currenttest, 256, L"Currently testing %lu", trial);
					swprintf(currenttime, 256, L"%.3f", (elapsed)/CLOCKS_PER_SEC);
					SendMessage(hStatus, SB_SETTEXT, 1 | 0, LPARAM (currenttest));
					SendMessage(hStatus, SB_SETTEXT, 3 | 0, LPARAM (currenttime));
					Sleep(10);
					delete [] currenttest, currenttime;
					Sleep(10);
					SendMessage(ProthProgress, PBM_STEPIT, NULL, NULL);

				
	/*		if (mpz_cmp (remainder, ZERO) != 0)
		{
			WCHAR currfac[256];
			swprintf(currfac, 256, L"Current trial: %lu", trial);
			SetDlgItemText(pWnd, IDC_DIGITS, currfac);
			ZeroMemory(currfac, 256);
			Sleep(100);
		}*/

		if (mpz_cmp (remainder, ZERO) == 0 && mpz_cmp_ui (squareroot, trial) > 0) //compares if remainder = 0.
					{						

						WCHAR* FoundIt = new WCHAR[256];

						swprintf(FoundIt, 256, L"Found the factor %lu.", trial);
						SendMessage(hStatus, SB_SETTEXT, 1 | 0, 
							LPARAM (FoundIt));
						SendMessage(hStatus, SB_SETTEXT, 0 | 0, 
							LPARAM (TEXT("Done.")));
						Sleep(100);
						ZeroMemory(FoundIt, 256);

						WCHAR szRealFac[256];
						swprintf(szRealFac, 256, L"%lu is a factor. Not prime.\r\n\r\nComputation took %.3f seconds.\r\n\r\n", trial, (elapsed)/CLOCKS_PER_SEC);

						SetDlgItemText(pWnd, IDC_FACTORS, szRealFac);
						ZeroMemory(szRealFac, 256);
			
						mpz_fdiv_q_ui (quotient, proth, trial);
						
						int len = mpz_sizeinbase (quotient, base) +2;			
						char * quostr = new char[len];				
						mpz_get_str (quostr, base, quotient);
						#ifdef UNICODE
						WCHAR * QUOw = new WCHAR[len];						
						mbstowcs(QUOw, quostr, len);
						SetDlgItemText(pWnd, IDC_OTHERF, QUOw);
						#else
						SetDlgItemText(pWnd, IDC_OTHERF, quostr);
						#endif

						WCHAR szquo[256];
						swprintf(szquo, 256, L"Factors are %lu and ", trial);
				
						SetDlgItemText(pWnd, IDC_ISPRIME, szquo);
						ZeroMemory(szquo, 256);

						SendMessage(ProthProgress, PBM_SETPOS, range, NULL);
						mpz_clear (remainder);
						mpz_clear (quotient);
						mpz_clear (proth);
						mpz_clear (squareroot);
						mpz_clear (rawroot);
						break;
					
						
					}

			else if (mpz_cmp_ui (squareroot, trial) < 0)

					{

						WCHAR szFac[128];
						swprintf(szFac, 128, L"Computation took %.3f seconds, but found no factors.\n", (elapsed)/CLOCKS_PER_SEC);
					
						CHAR tellMe[256];
						WCHAR tellThem[128];

						gmp_sprintf(tellMe, "Could not find any factors less than %Zd, the square root.\r\n\r\nThis number is likely prime!", squareroot);
						mbstowcs(tellThem, tellMe, CountOf(tellThem));

						SetDlgItemText(pWnd, IDC_FACTORS, szFac);
						ZeroMemory(szFac,4096);
						SendMessage(ProthProgress, PBM_SETPOS, range, NULL);
						MessageBox(NULL, L"This number appears prime!", L"Prime!", MB_ICONINFORMATION);

						SetDlgItemText(pWnd, IDC_ISPRIME, tellThem);
						SetDlgItemText(pWnd, IDC_OTHERF, L"There appear to be no factors...");
						
						SendMessage(hStatus, SB_SETTEXT, 1 | 0, 
						LPARAM (TEXT("Possible prime!")));

						ZeroMemory(tellMe, 256);
						ZeroMemory(tellThem, 128);

						mpz_clear (remainder);
						mpz_clear (quotient);
						mpz_clear (proth);
						mpz_clear (squareroot);
						mpz_clear (rawroot);
						break;
					}

				} //for

				break;
				
			}
			
			return FALSE;


Was This Post Helpful? 0
  • +
  • -

#5 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 3616
  • View blog
  • Posts: 11,262
  • Joined: 05-May 12

Re: Why does my program run?

Posted 20 August 2012 - 10:02 AM

Let me make sure I understand. If you press F5 in Visual Studio, the code runs correctly. If you press Ctrl-F5, Windows says that the programming is not responding.

Typically, problems like these are signs of one or more uninitialized variables being used.
Was This Post Helpful? 0
  • +
  • -

#6 vividexstance  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 678
  • View blog
  • Posts: 2,330
  • Joined: 31-December 10

Re: Why does my program run?

Posted 20 August 2012 - 10:13 AM

This part seems like it could be a problem:
char * bigstr = new char[len];						//Thanks Skydiver (D.I.C)
			mpz_get_str (bigstr, base, proth);
			#ifdef UNICODE
			WCHAR * BIGw = new WCHAR[len];
			mbstowcs(BIGw, bigstr, len);
			SetDlgItemText(pWnd, IDC_BIGNUM, BIGw);
			delete [] BIGw;
			#else
			SetDlgItemText(pWnd, IDC_BIGNUM, bigstr);
			#endif
			delete [] bigstr, BIGw;


I think you are confused about the comma operator. Correct me of I'm wrong, but that last line deletes bigstr only, and the result of the line is whatever BIGw points to.
You need to delete them both on separate lines.

*EDIT*: It's a good habit to set the pointers to NULL after deleting them, because trying to delete a pointer that has already been deleted is not good, but trying to delete a pointer to zero or NULL is harmless.

This post has been edited by vividexstance: 20 August 2012 - 10:17 AM

Was This Post Helpful? 0
  • +
  • -

#7 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 3616
  • View blog
  • Posts: 11,262
  • Joined: 05-May 12

Re: Why does my program run?

Posted 20 August 2012 - 10:18 AM

Also when you were debugging, did you actually trace through all the code to make sure that the loop eventually exits?

The loop condition on line 107 will only exit when proth >= trial. As best as I can tell, nothing inside the loop changes the value of proth. Since trial is set to 2 initially, and we are assuming that it is this loop that is causing the not responding issues, then the condition proth >= trial will never be true assuming unsigned integers can go to infinity. Unfortunately, unsigned integers will eventually roll over, back to 0. If proth is a negative number, then proth will still never be greater than or equal to trial, and you'll continue to loop forever.
Was This Post Helpful? 0
  • +
  • -

#8 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 3616
  • View blog
  • Posts: 11,262
  • Joined: 05-May 12

Re: Why does my program run?

Posted 20 August 2012 - 10:25 AM

And what is with all the Sleep() statements? Is it just to give your eyes a few fractions of a second to see the screen updates?

If you were assuming that the Sleep() would get rid of the not responding messages, as you've obviously seen, they do not. Part of the Windows detecting for non-responding applications is by checking for windows which are not pumping messages. Sleep() merely yields the processor to somebody else who may want it. It does not magically start pumping messages.

And please, please, please do not put in the VB equivalent do DoEvents() to pump messages. This is almost always the wrong solution. The correct solution is to restructure your program. If you have a long running operation, run that operation in another thread.
Was This Post Helpful? 0
  • +
  • -

#9 vividexstance  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 678
  • View blog
  • Posts: 2,330
  • Joined: 31-December 10

Re: Why does my program run?

Posted 20 August 2012 - 10:25 AM

Any of the arrays that you dynamically allocate with a hard-coded number like 128 or 256, should just be regular arrays because you know the size of the array before runtime so you don't need to allocate/deallocate memory for them. In this program, you really only need to allocate memory for the arrays for which you don't know the size until runtime.
Was This Post Helpful? 0
  • +
  • -

#10 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 3616
  • View blog
  • Posts: 11,262
  • Joined: 05-May 12

Re: Why does my program run?

Posted 20 August 2012 - 10:34 AM

vividexstance, unfortunately you don't know the full history of the code base he is working on. The rest of his code is living inside the WinProc() and there are tons of these little fixed size buffers. The compiler ends up creating a huge stack -- several megabytes worth each time the WinProc is entered. It was giving stack overflow problems not because of bad buffer writes, but simply because the stack was just that big. Basically the compiler was adding up all the stack buffers present within the WinProc.

Obviously, the correct solution is to break up the WinProc code into smaller functions, but nullcoding has still continued to keep hacking on the same code instead of stepping back and doing some refactoring.

This post has been edited by Skydiver: 20 August 2012 - 10:52 AM

Was This Post Helpful? 1
  • +
  • -

#11 snoopy11  Icon User is offline

  • Engineering ● Software
  • member icon

Reputation: 810
  • View blog
  • Posts: 2,405
  • Joined: 20-March 10

Re: Why does my program run?

Posted 20 August 2012 - 10:42 AM

Skydiver said

Quote

Obviously, the correct solution is to break up the WinProc code into smaller functions, but nullcoding has still continued to keep hacking on the same code instead of stepping back and doing some refactoring.


Yeah that is a huge F**k Off Button event :)
Was This Post Helpful? 1
  • +
  • -

#12 nullcoding  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 99
  • Joined: 08-July 12

Re: Why does my program run?

Posted 20 August 2012 - 12:30 PM

sigh

I would love to refactor the code. I was researching threading, and also installed Boost, but it's a little beyond my knowledge at this point.

Ideally I'd have the button's action run in a separate thread but I'm stuck on creating a testing function that actually "sees" all the controls it needs to reference.

I am vaguely aware that a window procedure can be implemented in a separate thread, but have also read that's a bad idea.

Since I put in Sleep() statements, things seem to have gotten more stable, but then again I also did some work with memory allocation (as several of you noticed).

The condition for the test loop is purely cosmetic - only there because a for loop needs 3 conditions. If it finds a factor, it breaks the loop. If it has tested up to the square root + 1, it breaks the loop. So it should not matter that the condition is never satisfied, although I'm probably gonna hear about how unorthodox and unnecessary that is.

I was also told (by a professional I know) that "No one uses that Windows API anymore," but I'm not about to start teaching myself C++/CLI just because it's "more common." So yes, the solution is to break up the window procedure.

Ideally, the function execution would be in a different thread, and I've gotten it to at least recognize the function and run the thread on button click. However, it does almost nothing.

It is meant to make sure the number in an edit box is not even, but in this function it always evaluates as 0 and tells me it can't test the number. Perhaps I'm lost on how to make a proper function or class in pure C++. :|

Quote

Let me make sure I understand. If you press F5 in Visual Studio, the code runs correctly. If you press Ctrl-F5, Windows says that the programming is not responding.


No not exactly. The first part is right. If I press Shift-F5 (that stops debugging), it stops debugging and kills the program. However, if I go to the build folder and open the executable, it will lock up rather than continuously updating the status bar and Windows will say it's not responding. If I leave it for a bit, it will respond.

For instance, I tried a specific combination of numbers. In Visual Studio debugger, it ran all the way and took 38 seconds. In standalone, it ran for 5 seconds and then froze up. But about 33 seconds later, it came back and gave me the same (correct) results.

For the record, I do know how to make classes and such, and reference their component functions and variables. I wrote a version of this program for Mac using Cocoa and Objective C that has the exact same functionality. Each button has its own interface header (.h) and implementation source (.m) files. Problem is there's no such thing as "Outlets" or "References" in VC++ - at least, not in the way in which I'm used to seeing them. It's also nothing like the Java program I wrote where window 1 and window 2 are different class files and the major component of window 2 is also a different file...

I have no choice but to learn on my own, since there's no class offered here teaching C or its derivatives. The fact I've gotten this far surprises me too.
Was This Post Helpful? 0
  • +
  • -

#13 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 3616
  • View blog
  • Posts: 11,262
  • Joined: 05-May 12

Re: Why does my program run?

Posted 20 August 2012 - 02:16 PM

View Postnullcoding, on 20 August 2012 - 12:30 PM, said:

I am vaguely aware that a window procedure can be implemented in a separate thread, but have also read that's a bad idea.


Only create a window procedure implement in a separate thread if the window that window procedure is supporting was also created on that other thread.

Bad:
WinMain() or MainWndProc()
{
    :
    HWND hwndOther = CreateWindow(...);
    CreateThread(..., OtherWndProc, hwndOther, ...);
    :
}



Good:
WinMain() or MainWndProc()
{
    :
    CreateThread(..., OtherUiThread, ...);
    :
}

void OtherUiThread(...)
{
    hwndOther = CreateWindow(...);
}


Was This Post Helpful? 0
  • +
  • -

#14 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 3616
  • View blog
  • Posts: 11,262
  • Joined: 05-May 12

Re: Why does my program run?

Posted 20 August 2012 - 02:22 PM

View Postnullcoding, on 20 August 2012 - 12:30 PM, said:

I would love to refactor the code.


See this Tutorial: Using WindowsX.h for Better Code Organization and Message Cracking

Which reminds me I better get cracking on writing the next part of the tutorial about encapsulating code in a class. (Sorry, I couldn't resist the pun.)
Was This Post Helpful? 0
  • +
  • -

#15 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 3616
  • View blog
  • Posts: 11,262
  • Joined: 05-May 12

Re: Why does my program run?

Posted 20 August 2012 - 02:45 PM

Slightly off topic, I'll repeat my observation I made in post #72:

Quote

(As aside, I've noticed that mathematicians, and theoretical scientist don't seem to mind copying, pasting, and duplicating code. Is there something in the mindset or world view that lets this happen?)


My latest evidence was that recent thread with the algae.

Back on topic:
You don't even have to go to that extreme of refactoring every message handler out to function. As a first step, you could simply get rid of some of the repetitive code by moving them into functions as I'd suggested and hinted at in posts #92, #88, and #64.

Merely removing the duplicate code and calling a helper function would save you a ton of stack space, as well as make the code much easier to read.

View Postnullcoding, on 20 August 2012 - 12:30 PM, said:

Ideally I'd have the button's action run in a separate thread but I'm stuck on creating a testing function that actually "sees" all the controls it needs to reference.


Normally, when you run another thread to do a long running operation you collect all the information it needs, package that up into a class or structure, and then start the other thread passing in the class or structure. If you want the UI to be notified of the progress, then the UI registers for events from that thread through callback functions. There is no need for the long running operation to see the Windows controls since its primary focus is to do an operation, not update the view.
Was This Post Helpful? 0
  • +
  • -

  • (3 Pages)
  • +
  • 1
  • 2
  • 3