Stack overflow + Mfc



  • Guten Abend,

    ich arbeite schon mehrere Wochen an einem Projekt über eine Signalverarbeitung mit C++ MFC. Die Buffergröße ist dabei um die 50.000 - 100.000 Werte und erstmal 4 Kanäle . Das Ganze hat bis gestern ganz hübsch funktioniert - bisschen langsam, aber das war ja klar bei der Größenordnung. Insgesamt gibt es 5 Methoden wie filtern, spike detection usw. Dazu noch 3 Methoden um die Daten und ein paar Informationen zu speichern, 4 Methoden für Buttons, eine große Hauptmethode die in bestimmten Zeitabständen aufgerufe wird und alles einmal durchläuft (Sowie die typischen MFC Methoden wie OnInitDialog usw). Außerdem hab ich natürlich einen ganzen Haufen Variablen: für jeden Kanal 2, dann noch ca 15 um die Informationen von der GUI ins Programm zu übertragen. Und oben drauf noch ein Scope der 1 Kanal anzeigt.

    ALso wie man sieht verdammt viel. Ich kann auch wenn gewünscht gern tiefer ins Detail gehen.

    Nach den letzten Änderungen kann ich das Programm nur noch mit einem Kanal starten und auch da nur ein paar Sekunden bis es heißt stack overflow. Ich habe wohl zu viel ins Programm geschrieben, aber das ist meine Vorgabe und ich bin fast am Ziel. Soweit wie ich mich bisher eingelesen habe ist der Grund für stack overflow, dass nicht genügend Speicher vorhanden ist. Gibt es eine Möglichkeit an mehr Speicher zu kommen ? Oder was ist die beste Möglichkeit den Speicher effizienter zu nutzen? Ich weiß das ich viele lokale Variablen und viele Methoden meiden soll. Leider komm ich oft nicht drumrum. Gut ich könnte alles in eine Methode schreiben - da geht aber erstmal die Übersicht verloren und zum Zweiten müsste ich dann alles 4 mal schreiben (für jeden Kanal). Momentan läuft das ganze noch objekt orientiert.

    Man hört sicher das ich kein Informatiker bin - ich bin Maschinenbauer und hatte nur ein Semester Informatik. So ich hoffe mir kann jmd dabei helfen 🙂

    Mfg



  • Du redest viel zu viel um den heißen Brei herum. Was das Programm macht, interessiert keinen.
    Stack Overflow heißt wohl, es liegen zu viele Daten auf dem Stack. Hast ja selber schon erkannt. Alles andere kann man so allgemein nicht beantworten. Stell eine konkrete Frage oder zeig etwas Code oder so, dann kann man vielleicht über eine andere Lösung diskutieren.



  • Hallo,

    ich würds mal mit dynamischer Speicheranforderung mittels new & delete[] probieren für die ganzen Arrays, damit du nicht den Stack, sondern den Heap benutzen kannst...
    Bringt einige Vorteile mehr mit, als nur die Größe der hinterlegbaren Speichermengen 😉



  • Ich wollte damit nur mal die Größenordnungen andeuten ich scheib da nämlich locker paar hunderttausend werte rum pro sekunde ich werd mal paar methoden posten:

    int CContinuousAcquireDlg::Startrx5() {
    	if (m_rx5.ConnectRX5("GB", 1) ==0)
    		if (m_rx5.ConnectRX5("USB", 1) == 0) {
    			AfxMessageBox("Error connecting to rx5.");
    			return 0;
    		}
    
    	m_rx5.ClearCOF();
    
    	if (m_rx5.LoadCOF("C:\\TDT\\ActiveX\\ActXExamples\\RP_files\\Continuous_Acquire.rcx") == 0) {
    		AfxMessageBox("Error loading .rcx file");
    		return 0;
    	}
    
    	return m_rx5.Run();
    }
    
    void CContinuousAcquireDlg::OnLoadClick() {
    
    	if (!Startrx5())
    		return;
    
    	// initialize time array
    	timer = new double[bufpts];	
    	for (int i = 0; i < bufpts; i++)
    		timer[i] = i / sample_rate;
    
    	data1 = new float[bufpts];
    	data2 = new float[bufpts];
    	data3 = new float[bufpts];
    	data4 = new float[bufpts];
    
    	spike1 = new float[20*bufpts];
    	spike2 = new float[20*bufpts];
    	spike3 = new float[20*bufpts];
    	spike4 = new float[20*bufpts];
    
    	CString local;
    	m_User.GetWindowTextA(local);
    	CString local2;
    	m_File.GetWindowTextA(local2);
    
    	if(local.IsEmpty() != true && local2.IsEmpty() != true)
    		{
    		m_load_button.EnableWindow(FALSE);
    		m_start_button.EnableWindow(TRUE);
    		m_stop_button.EnableWindow(TRUE);
    		}
    	else
    	{
    		AfxMessageBox("Enter Username and Filepath.");
    	}
    
    	acquire = false;
    	m_samples_text = "0";
    	UpdateData(FALSE);
    	samples_acquired = 0;
    
    void CContinuousAcquireDlg::WriteToFile(float *data, int points) {
    	fout.write((char *) data, points * sizeof(float));
    }
    
    void CContinuousAcquireDlg::OnStartClick() {
    	CString strFolder;
    	strFolder = GetFolder();
    
    	CString local;
    	m_File.GetWindowText(local);
    	local = strFolder + "\\" + local + ".f32";
    	const char *outfile = local; 
    
    	fout.open(outfile, ios::out | ios::binary);	
    
    	m_start_button.EnableWindow(FALSE);
    	m_stop_button.EnableWindow(TRUE);
    
    	time ( &rawtime );
    	timeinfo = localtime ( &rawtime );
    
    	m_Info.GetWindowText(local);
    	local = strFolder + "\\" + local + ".txt";
    	myfile.open (local);
    	myfile << "Starttime: ";
    	myfile << asctime (timeinfo);
    
    	acquire = true;
    	high = false;
    
    	m_rx5.SoftTrg(1);
    
    	SetTimer(1, 10, NULL);
    
    }
    
    float *CContinuousAcquireDlg::Butterworth(float *data)
    { 
    	float *filterData[1];
    	filterData[0] = new float[bufpts];
    	filterData[0] = data;
    
    	CString local;
    	m_Order.GetWindowText(local);
    	order = atof(local);
    
    	m_Center.GetWindowText(local);
    	center_frequency = atof(local);
    
    	m_Width.GetWindowText(local);
    	band_width = atof(local);
    
    	Dsp::SimpleFilter <Dsp::Butterworth::BandPass <6>, 1> butter;
    	butter.setup (order,    // order
    				sample_rate,// sample rate
    				center_frequency, // center frequency
    				band_width);  // band width 
    
    	butter.process (bufpts, filterData);
    
    	return filterData[0];
    
    }
    
    float *CContinuousAcquireDlg::SpikeDetection(float *filterData)
    {
    
    	CString local;
    	m_Low.GetWindowText(local);
    	lowlimit = atof(local);
    	m_High.GetWindowText(local);
    	highlimit = atof(local);
    
    	for (int i = 0; i < bufpts; i++)
    	{
    		if (abs(filterData[i])> lowlimit && abs(filterData[i]) < highlimit)
    		{
    			filterData[i] = abs(filterData[i]);
    		}
    		else 
    		{
    			filterData[i] = 0;
    		}
    	}
    	return filterData;
    }
    
    float *CContinuousAcquireDlg::SmoothTransition(float *spike, float *newspike)
    {
    
    for (int i = 0; i<bufpts; i++)
    {
    	spike[(counter*bufpts)+i]= newspike[i];
    
    }
    
    for (int i = 0; i<(counter+1)*bufpts; i++)
    {
    
    	if (spike[i]>0)
    	{
    		for(int j = 0;j<24;j++)
    		{
    			spike[i+j+1]=0;
    		}
    	}
    }
    return spike;
    }
    
    float *CContinuousAcquireDlg::Framing(float *spike)
    {	
    	int spikecount = 0;
    
    	for (int i = 0; i < (1000* bufpts/(sample_rate*frame_size)); i++)
    	{
    		for (int j = 0; j < (sample_rate * frame_size/1000); j++)
    		{
    			if (spike[i*(sample_rate * frame_size/1000)+j] > 0)
    			{
    				spikecount++;
    			}
    		}
    		spike[i]=spikecount;
    		spikecount=0;
    	}
    	return spike;
    }
    
    float *CContinuousAcquireDlg::Decision(float *frames)
    {
    	float *decision;
    	decision = new float[bufpts];
    	int j = 0;
    	for (int i = 0; i<(counter+1)*bufpts; i++)
    	{
    		if(frames[i] >= 30 && frames[i] <= 35)
    		{
    			if(frames[i+1] >=30 && frames[i+1] <=35)
    			{
    				if(frames[i+2] >= 30 && frames[i+2] <= 35)
    				{
    					decision[j] = ((counter*bufpts)+i)/sample_rate;
    					j++;
    				}
    			}
    		}
    	}
    	return decision;
    }
    
    void CContinuousAcquireDlg::OnTimer(UINT nIDEvent) {
    	static int offset = 0;
    
    	if(acquire) {
    		curindex = m_rx5.GetTagVal("index");
    		m_index_text.Format("%.0f", curindex);
    		UpdateData(FALSE);
    
    		if(high) {
    			while(curindex > bufpts) { 
    				curindex = m_rx5.GetTagVal("index");
    				m_index_text.Format("%.0f", curindex);
    				UpdateData(FALSE);
    			}
    		} else {
    			while(curindex < bufpts) { 
    				curindex = m_rx5.GetTagVal("index");
    				m_index_text.Format("%.0f", curindex);
    				UpdateData(FALSE);
    			}
    		}
    
    		// read segment and write it to file
    
    		if(m_rx5.ReadTag("dataout1", data1, offset, bufpts) == 0)
    			AfxMessageBox("Error transferring data.");
    		//if(m_rx5.ReadTag("dataout1", data2, offset, bufpts) == 0)
    		//	AfxMessageBox("Error transferring data.");
    		//if(m_rx5.ReadTag("dataout1", data3, offset, bufpts) == 0)
    		//	AfxMessageBox("Error transferring data.");
    		//if(m_rx5.ReadTag("dataout1", data4, offset, bufpts) == 0)
    		//	AfxMessageBox("Error transferring data.");
    
    		Scope.Channels[ 0 ].Data.SetYData( data1, bufpts );
                    WriteToFile(data1, bufpts);
    		data1=Butterworth(data1);
                    Scope.Channels[ 1 ].Data.SetYData( data1, bufpts );
    	        WriteToFile(data1, bufpts);
                    data1=SpikeDetection(data1);
    
                    spike = SmoothTransition(spike, data1);
    
                    Decision(spike);
    
                    WriteToFile(data[i], bufpts);
    
    			counter++;
    
    			samples_acquired += bufpts;
    			m_samples_text.Format("%d", samples_acquired);
    			UpdateData(FALSE);
    
    			// check to see if data is transferring fast enough
    			curindex = m_rx5.GetTagVal("index");
    			m_index_text.Format("%.0f", curindex);
    			UpdateData(FALSE);
    			if(high) {
    				if (curindex > bufpts) {
    					AfxMessageBox("Error: transfer rate too slow.");
    					m_rx5.SoftTrg(2);
    					m_rx5.Halt();
    					acquire = false;
    				}
    			} else {
    				if (curindex < bufpts) {
    					AfxMessageBox("Error: transfer rate too slow.");
    					m_rx5.SoftTrg(2);
    					m_rx5.Halt();
    					acquire = false;
    				}
    			}
    
    			// set for next time
    			if(high) {
    				high = false;
    				offset = 0;
    			} else {
    				high = true;
    				offset = bufpts;
    			}
    
    	}
    
    	CDialog::OnTimer(nIDEvent);
    }
    

    So damit werdet ihr mich wahrscheinlich in der Luft zerreißen aber was solls ^^

    das mit delete is ne sehr gute idee damit sollte sich doch gut was einsparen lassen 😉 bin für weitere tipps offen

    ist alles üprigens unfertig!

    Mfg



  • Das war jetzt schon wieder zu viel 😉 Auf den ersten Blick benutzt du ja auch schon new, ich seh jetzt nicht wo du zu viele Daten auf dem Stack liegen, hab aber ehrlich gesagt auch keine Lust, mich in so viel Code reinzudenken.
    Kannst du das Problem eingrenzen? Du kriegst doch eine Exception. An welcher Stelle tritt sie auf?



  • wenn ich alles laufen lassen schafft er es nicht mal das programm zu öffnen das hörts beim debuggen schon auf

    wenn ich nur einen kanal nehme dann läuft er ein paar sekunden und verweißt auf eine stelle in wincore.cpp allerdings kann ich dir das jetzt gerade nicht sagen weil ich nicht mehr im labor bin



  • Du musst dir den Callstack anschauen, irgendwo weiter unten wird auch dein Code sein. Dann kannst du das Problem vielleicht eingrenzen.



  • Ok danke erstmal ich schau morgen nochmal nach un schreibe dann nochmal!



  • Also wenn ich das ganze jetzt auf einen kanal reduziere und dann alles durchlaufen lassen will ist der fehler in der iosfwd Zeile 545

    static int_type __CLRCALL_OR_CDECL to_int_type(const _Elem& _Ch)
    		{	// convert character to metacharacter
    		return ((unsigned char)_Ch);
    		}
    

    jetzt habe ich alle bearbeitung abgestalten und dann stueck fuer stueck wieder aktiviert dann ist der fehler hier:

    float *CContinuousAcquireDlg::Decision(float *frames)
    {
    	float *decision;
    	decision = new float[bufpts];
    	int j = 0;
    	for (int i = 0; i<(counter+1)*bufpts; i++)
    	{
    		if(frames[i] >= 30 && frames[i] <= 35)
    		{
    			if(frames[i+1] >=30 && frames[i+1] <=35)
    			{
    				if(frames[i+2] >= 30 && frames[i+2] <= 35)
    				{
    					decision[j] = ((counter*bufpts)+i)/sample_rate;
    					j++;
    				}
    			}
    		}
    	}
    	return decision;
    }
    

    in der 1. if abfrage ich sehe nur leider nicht was daran falsch sein soll



  • Hey,

    kann es sein, dass i bzw. i+1 und i+2 einfach irgendwann zu groß werden und somit auf einen Arrayindex zugreifen wollen, das gar nicht existiert?

    Ich konnte bisher auch nirgends lesen, was bufpts ist, oder auch von welchem typ bzw. wie groß!?



  • bufpts ist eine konstante wollte jetzt nicht alles reinkopieren
    aber das der array zu weit zaehlt ist ein punkt da haste recht werd das ueberarbeiten



  • So ich habe jetzt alles zu ende programmiert wie ich das gerne haette und ich schaff genau einen buffer voll zu kriegen dann kommt:

    no Source available

    so symbols are loaded for any call stack frame. the source code cannot be displayed.

    Call stack location

    00000000()

    Ich werd jetzt wohl versuchen die Methoden groesser zu machen vllt hab ich damit ja erfolg



  • Dann hast Du Dir den Callstack überschrieben... und zwar vermutlich mit einer Variable, die lokal in einer Methode definiert ist.


Log in to reply