Click here to Skip to main content
15,112,453 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
I have some code that programs a dialog box to take in information from an outside instrument and display the values on the screen. When I compile and run my code in Debug mode it runs just fine, but when I switch to Release the program crashes and tells me I am accessing something incorrectly. After some searching on the web I configured my compiler to run without optimizations and also tried to enable debugging info in the project configurations (for Release). However, it does not stop at breakpoints in the Release version and so troubleshooting has been difficult. I get the impression that there is something not being initialized correctly, but I cannot find the problem. Can anyone help?

Here is the implementation file for the dialog box.

#include "stdafx.h"
#include "winstm.h"
#include "Dlg_Channel_Meter.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;

// CDlg_Channel_Meter dialog

CDlg_Channel_Meter::CDlg_Channel_Meter(CWnd* pParent /*=NULL*/)
	: CDialog(CDlg_Channel_Meter::IDD, pParent)
	, m_DAC_Dev(0)

	theInst = ((CWinSTMApp*)AfxGetApp())->GetInstrument();

	m_Scan_Chan[0] = 0;
	m_Scan_Chan[1] = 1;
	m_Scan_Chan[2] = 2;
	m_Scan_Chan[3] = 3;
	m_Scan_Chan[4] = 4;
	m_Scan_Chan[5] = 5;
	m_Scan_Chan[6] = 6;
	m_Scan_Chan[7] = 7;

	m_pThread = NULL;
	m_ADC0 = _T("");
	m_ADC1 = _T("");
	m_ADC2 = _T("");
	m_ADC3 = _T("");
	m_ADC4 = _T("");
	m_ADC5 = _T("");
	m_ADC6 = _T("");
	m_ADC7 = _T("");

	ticks = 0;
	counts = 0;
	upperlimit = 10;  //any number up to 100, 10 = 10 cyles, each cycle = 100 ms, so 10 = 1 seconds

	for (int i = 0; i < 8; i++)
		for (int c = 0; c < upperlimit; c++)
			m_ADC_a_array[i][c] = 0;

	m_ADC_a.SetSize (8);
	m_ADC_std.SetSize (8);

	m_ADC_a[0] = _T("");
	m_ADC_a[1] = _T("");
	m_ADC_a[2] = _T("");
	m_ADC_a[3] = _T("");
	m_ADC_a[4] = _T("");
	m_ADC_a[5] = _T("");
	m_ADC_a[6] = _T("");
	m_ADC_a[7] = _T("");

	m_ADC_std[0] = _T("");
	m_ADC_std[1] = _T("");
	m_ADC_std[2] = _T("");
	m_ADC_std[3] = _T("");
	m_ADC_std[4] = _T("");
	m_ADC_std[5] = _T("");
	m_ADC_std[6] = _T("");
	m_ADC_std[7] = _T("");


	if(AfxGetApp()->GetProfileInt("UEI DAC","Enable",0))
		m_DAC_Dev = -1;
		m_DAC_Dev = theInst->m_DAQ.m_6508_Device;


void CDlg_Channel_Meter::DoDataExchange(CDataExchange* pDX)
	DDX_Text(pDX, IDC_6052E_ADC0, m_ADC0);
	DDX_Text(pDX, IDC_6052E_ADC1, m_ADC1);
	DDX_Text(pDX, IDC_6052E_ADC2, m_ADC2);
	DDX_Text(pDX, IDC_6052E_ADC3, m_ADC3);
	DDX_Text(pDX, IDC_6052E_ADC4, m_ADC4);
	DDX_Text(pDX, IDC_6052E_ADC5, m_ADC5);
	DDX_Text(pDX, IDC_6052E_ADC6, m_ADC6);
	DDX_Text(pDX, IDC_6052E_ADC7, m_ADC7);

	DDX_Text(pDX, IDC_6052E_ADC0_a, m_ADC_a[0]);
	DDX_Text(pDX, IDC_6052E_ADC1_a, m_ADC_a[1]);
	DDX_Text(pDX, IDC_6052E_ADC2_a, m_ADC_a[2]);
	DDX_Text(pDX, IDC_6052E_ADC3_a, m_ADC_a[3]);
	DDX_Text(pDX, IDC_6052E_ADC4_a, m_ADC_a[4]);
	DDX_Text(pDX, IDC_6052E_ADC5_a, m_ADC_a[5]);
	DDX_Text(pDX, IDC_6052E_ADC6_a, m_ADC_a[6]);
	DDX_Text(pDX, IDC_6052E_ADC7_a, m_ADC_a[7]);

	DDX_Text(pDX, IDC_6052E_ADC0_std, m_ADC_std[0]);
	DDX_Text(pDX, IDC_6052E_ADC1_std, m_ADC_std[1]);
	DDX_Text(pDX, IDC_6052E_ADC2_std, m_ADC_std[2]);
	DDX_Text(pDX, IDC_6052E_ADC3_std, m_ADC_std[3]);
	DDX_Text(pDX, IDC_6052E_ADC4_std, m_ADC_std[4]);
	DDX_Text(pDX, IDC_6052E_ADC5_std, m_ADC_std[5]);
	DDX_Text(pDX, IDC_6052E_ADC6_std, m_ADC_std[6]);
	DDX_Text(pDX, IDC_6052E_ADC7_std, m_ADC_std[7]);

	DDX_Text(pDX, IDC_STATIC_CH0, theInst->m_ADC_Description[0]);
	DDX_Text(pDX, IDC_STATIC_CH1, theInst->m_ADC_Description[1]);
	DDX_Text(pDX, IDC_STATIC_CH2, theInst->m_ADC_Description[2]);
	DDX_Text(pDX, IDC_STATIC_CH3, theInst->m_ADC_Description[3]);
	DDX_Text(pDX, IDC_STATIC_CH4, theInst->m_ADC_Description[4]);
	DDX_Text(pDX, IDC_STATIC_CH5, theInst->m_ADC_Description[5]);
	DDX_Text(pDX, IDC_STATIC_CH6, theInst->m_ADC_Description[6]);
	DDX_Text(pDX, IDC_STATIC_CH7, theInst->m_ADC_Description[7]);


BEGIN_MESSAGE_MAP(CDlg_Channel_Meter, CDialog)

// CDlg_Channel_Meter message handlers

BOOL CDlg_Channel_Meter::OnInitDialog() 

	for(int i = 0; i <8 ; i++)
		m_6052_IO_State[i] = false;
		/////////////////////////m_6704_IO_State[i] = false;

	// set update timer
	SetTimer(1,100,NULL); // JJS, second parameter is 100 ms


	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE

void CDlg_Channel_Meter::OnTimer(UINT nIDEvent) 

	for (int i = 0; i < 8; i++)
		m_ADC_a_array[i][counts] = m_ADC_ddata[i];


	CStatic *stat=NULL;
	if (ticks >= 1)
		m_ADC0.Format("%.4f V",m_ADC_ddata[0]);
		m_ADC1.Format("%.4f V",m_ADC_ddata[1]);
		m_ADC2.Format("%.4f V",m_ADC_ddata[2]);
		m_ADC3.Format("%.4f V",m_ADC_ddata[3]);
		m_ADC4.Format("%.4f V",m_ADC_ddata[4]);
		m_ADC5.Format("%.4f V",m_ADC_ddata[5]);
		m_ADC6.Format("%.4f V",m_ADC_ddata[6]);
		m_ADC7.Format("%.4f V",m_ADC_ddata[7]);

		stat = (CStatic*)GetDlgItem(IDC_6052E_ADC0);
		stat = (CStatic*)GetDlgItem(IDC_6052E_ADC1);
		stat = (CStatic*)GetDlgItem(IDC_6052E_ADC2);
		stat = (CStatic*)GetDlgItem(IDC_6052E_ADC3);
		stat = (CStatic*)GetDlgItem(IDC_6052E_ADC4);
		stat = (CStatic*)GetDlgItem(IDC_6052E_ADC5);
		stat = (CStatic*)GetDlgItem(IDC_6052E_ADC6);
		stat = (CStatic*)GetDlgItem(IDC_6052E_ADC7);
		ticks = 0;

	if (counts >= upperlimit)
		double average[8];
		double std[8];
		for (int i = 0; i < 8; i++)
			average[i] = 0;
			std[i] = 0;

		for (int i = 0; i < 8; i++)
			for (int c = 0; c < upperlimit; c++)
				average[i] += m_ADC_a_array[i][c];
			average[i] = average[i] / upperlimit;
			for (int c = 0; c < upperlimit; c++)
				double diff = (average[i] - m_ADC_a_array[i][c]);
				std[i] += (diff * diff);
			std[i] = sqrt(std[i] / upperlimit);

			m_ADC_a[i].Format("%.4f V",average[i]);
			m_ADC_std[i].Format("%.4f V",std[i]);

		stat = (CStatic*)GetDlgItem(IDC_6052E_ADC0_a);
		stat = (CStatic*)GetDlgItem(IDC_6052E_ADC1_a);
		stat = (CStatic*)GetDlgItem(IDC_6052E_ADC2_a);
		stat = (CStatic*)GetDlgItem(IDC_6052E_ADC3_a);
		stat = (CStatic*)GetDlgItem(IDC_6052E_ADC4_a);
		stat = (CStatic*)GetDlgItem(IDC_6052E_ADC5_a);
		stat = (CStatic*)GetDlgItem(IDC_6052E_ADC6_a);
		stat = (CStatic*)GetDlgItem(IDC_6052E_ADC7_a);

		stat = (CStatic*)GetDlgItem(IDC_6052E_ADC0_std);
		stat = (CStatic*)GetDlgItem(IDC_6052E_ADC1_std);
		stat = (CStatic*)GetDlgItem(IDC_6052E_ADC2_std);
		stat = (CStatic*)GetDlgItem(IDC_6052E_ADC3_std);
		stat = (CStatic*)GetDlgItem(IDC_6052E_ADC4_std);
		stat = (CStatic*)GetDlgItem(IDC_6052E_ADC5_std);
		stat = (CStatic*)GetDlgItem(IDC_6052E_ADC6_std);
		stat = (CStatic*)GetDlgItem(IDC_6052E_ADC7_std);

		for (int i = 0; i < 8; i++)
			for (int c = 0; c < upperlimit; c++)
				m_ADC_a_array[i][c] = 0;
		counts = 0;

#endif // #ifdef HARDWARE_NI
Updated 27-Sep-12 13:26pm
Sergey Alexandrovich Kryukov 27-Sep-12 18:25pm
That happens, unfortunately. You see, this is not the complete project, so, the first thing to suspect is "race condition". If there more then one thread, by any chance?
AndrewG1231 27-Sep-12 19:15pm
Yes, it seems so. The dialog is listed as the Main Thread, but there are several Worker Threads listed. The worker threads are catagorized as Win32 Thread and _TppWaiterpthread@4. Thanks for the fomating update, it seems the site has changed its look.
Sergey Alexandrovich Kryukov 27-Sep-12 18:27pm
Code format fixed. Put the code in the tag <pre lang="C++">...</pre>
TRK3 27-Sep-12 19:03pm
A couple of things to watch for:

1. When you compile for debug, Microsoft initializes uninitialized stack variables and heap data to specific values -- when you compile for release, those uninitialized values are whatever is in memory.

2. If you have static variables that are initialized to instances of some class, the constructors for those instances are called at startup -- but not in any specified order. The actual order is defined at compile/link time but isn't defined per the spec and seems to differ between debug and release code sometimes. So, if you have static objects where the order of construction matters, you have to instantiate them yourself after startup.

3. When you can't use the debugger, you can always resort to logging messages to a file. With enough logging statements, you can narrow down where your code is failing.
Sergey Alexandrovich Kryukov 27-Sep-12 19:39pm
Good points, really. I described one more, but... look at the code. Such things don't work, usually; and when their work... it's worse than if they did not.
Please see my answer... this is sad...
TRK3 27-Sep-12 20:10pm
I actually found I was unable to look at the code...

I still can't.

I took one glance at it, and decided it was written by a hardware engineer, or by an intern or programmer fresh out of school with little or no Microsoft experience and little real world experience (it's the sort of project you'd throw at that kind of person).

Assuming that's the level of our OP, I also assumed he hadn't written multi-threaded code and just needed some pointers to get him started on figuring out his problem.

If he is any good, he'll take it from here, and a couple of years from now he'll actually be writing code that's good enough to use in production. (I could tell you horror stories about the first code I ever wrote professionally.)

(I am still not convinced his program is truly multi-threaded. Most windows programs have a few extra threads kicking around tha show up in the debugger -- but those threads are things Microsoft spawned and aren't likely to be an issue.)

AndrewG1231 27-Sep-12 20:40pm
You are actually pretty close to describing my situation. I am a graduate student that had basic programming skills, and by basic I mean some classes on C++ at one point. My project has depended on developing hardware and modifying a program that I inherited. I have been learning through tutorials (which apparently I need more of) and the feedback on here about specific problems (which I am grateful for). It is my intention to be as respectful and professional as I can on here...not to post terrible code and uneducated questions. I really enjoy this site and have found the articles quite informative. Thanks for all the help, and I am sorry that I have given you 'programming' nightmares...
Sergey Alexandrovich Kryukov 27-Sep-12 21:06pm
All right, the first and most useful skill you already have: the ability to use criticism in a constructive way -- my respect for that.
TRK3 28-Sep-12 12:49pm
It's not really a programming nightmare.

It's just pretty obvious that you aren't familiar with the ins and outs of MFC and that you probably don't have a lot of experience maintaining old code.

If you inherited the program -- did the release build work before you made any modifications? If so, the first place to look would be at the modifications you made, possibly commenting them out and then adding them back in one at a time to see when it breaks. It's not necessarily true that the bug is in your code, but it's the first place to look. Once you find the change that causes the code to break, you've got it narrowed down and can hopefully determine if there is something wrong with that code itself, or you can trace what effects that change have on whatever is breaking.

1 solution

[After OP answered the question about possible multiple threads, see the comments to the question:]

So, more then one thread could be the case? OK. One of the known reasons of different results in different configurations (and anything different in environment as well) is the incorrect dependency on the order of execution, also know as under a "jargon" name "race condition". Generally, the code does not work correctly in all cases, but in some configurations it works by some random reason, because one thread comes to some point sooner then the other one. It creates an illusion that everything is correct. The change in configuration (or anything in the environment) changes timing, and this "random" illusion of correctness disappears.

(One trivial "non-fatal" example: imagine that one thread multiply one shared variable by 3, and another one adds 4 to the result. Imagine that the shared access is written correctly. Nevertheless, the final result depends on which thread was the first.)

Please see:[^].

How to detect it? Difficult. And often the detection does not even makes sense, because the code should be designed accurately, and then such problems do not appear, so the design should be changed anyway, even without spotting the exact bug.

Besides, this is not the only possible reason for the problem. Now, the code does not show anything to suspect specifically, but has all the signs of the very, very illiterate programming, so I would not be surprised by any kind of problem. In particular, 12 identical fragments of code are repeated 8 times each. What, you don't know how to use the cycle? No, you use some. Don't know how to abstract out some values by making the function parameters? Maybe; the code shows only one function. In any non-nonsense programming, nothing is ever repeated in code.

This is not code at all, no sense to continue it in any way. What to do? I don't know; learn some basic programming, may be.

Sorry, not very optimistic conclusions, but what else could I possibly advise? Even if I was able to spot and fix your problem at once, it would not make your code acceptable.


This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
Top Experts
Last 24hrsThis month

CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900