Weird Problem

Started by
7 comments, last by Zahlman 18 years, 8 months ago
Hey not sure whatsup here, has anyone ever had this problem before. What Im doing is actually just resizing an array that was made using DMA. Now the problem is, when I initially make the array, I set all the elements of the array to NULL. Now as I go through the debugger, it does show that they are NULL. Then I change some of the elements within the array to a value the others staying NULL. Okay, so that all looks correct, now here comes the wierd part, I then pass that array into a function that is going to resize the array, currently tryin to make the array bigger. Now before I do anything to the array, I look at the contents of the array in the debugger, and low and behold, all of a sudden my NULL values that I had before, are now junk values, mostly negative numbers that look like -2.5301711256524607e-098. Does anyone know how to solve this? Could it just be my computer, If you need source code I'll post it, but it seems to be all correct to me. Thanks ahead of time, for your time and effort in helping me. Again I would like to thank you. I've been asked to post my code, so here it is... you'll notice Im tryin a few things. Header File

// CStack class
#include <iostream>
using namespace std;

class CStack {
public:
	// Constructors
	CStack(unsigned int iGFactor = 3);
	CStack(CStack const &obj);
	~CStack(void);
	
	// Operators
	CStack& operator =(CStack const &rRHArg);
	CStack& operator +=(double const value);

	// Methods
	CStack& Push(double const value);
	double Pop(void);
	void Clear(void);
	unsigned int Size(void);
	unsigned int Capacity(void);

private:
	double* m_Array;
	unsigned int m_iGFactor;
	unsigned int m_iMultiple;

protected:
	double* ResizeArray(void);
	//double* ResizeArray(double* array);
};

CStack::CStack(unsigned int const iGFactor):m_iGFactor(iGFactor), m_iMultiple(1){

	if(iGFactor==0)
		throw("Invalid growth factor!");

	m_Array = new double[iGFactor];
	for(int i=0; i<iGFactor; i++)
		m_Array = 0;
}

CStack::CStack(CStack const &obj):m_iGFactor(obj.m_iGFactor){
	m_iMultiple = obj.m_iMultiple;

	m_Array = new double[m_iGFactor*m_iMultiple];
	for(unsigned int i=0; i< (m_iGFactor*m_iMultiple); i++)
		if(obj.m_Array)
			m_Array = obj.m_Array;
		
}

CStack::~CStack(void){
	delete [] m_Array;
}

CStack& CStack::operator =(CStack const &rRHArg)
{
	// for the expression a = b, a will be *this, and b will be rRHArg 
	if (&rRHArg != this) 			// check for self assignment 
	{ 
		this->~CStack();		//or delete 
		
		m_iGFactor = rRHArg.m_iGFactor;
		m_iMultiple = rRHArg.m_iMultiple;

		m_Array = new double[m_iGFactor*m_iMultiple];
		for(unsigned int i=0; i< (m_iGFactor*m_iMultiple); i++)
			if(rRHArg.m_Array)
				m_Array = rRHArg.m_Array;
	} 
	return *this;	//allows chaining of the = operator
}

CStack& CStack::Push(double const value){

	bool bFull = true;
	for(unsigned int i=(m_iGFactor*m_iMultiple)-m_iGFactor; i<(m_iGFactor*m_iMultiple); i++){
		if(!m_Array){
			bFull = false;
			m_Array = value;
			break;
		}
	}

	if(bFull){
		m_iMultiple++;
		m_Array = ResizeArray();
		//m_Array = ResizeArray(m_Array);
		m_Array[m_iGFactor*m_iMultiple-m_iGFactor] = value;
	}

	return *this;
}

//double* CStack::ResizeArray(double array[]){
//
//	double* NewArray = new double[m_iGFactor*m_iMultiple];
//	for(unsigned int i=0; i<(m_iGFactor*m_iMultiple); i++){
//		if(array)
//			NewArray = array;
//		else
//			NewArray = NULL;
//	}
//	
//	delete [] array;
//
//	return NewArray;
//}

double* CStack::ResizeArray(void){

	double* NewArray = new double[m_iGFactor*m_iMultiple];
	for(unsigned int i=0; i<(m_iGFactor*m_iMultiple); i++)
		if(m_Array)
			NewArray = m_Array;

	delete [] m_Array;

	return NewArray;
}

CStack& CStack::operator +=(double const value){
	this->Push(value);
	return *this;
}

double CStack::Pop(void){

	double value;
	bool bEmpty = true;
	int iIndex;

	for(int i=(m_iGFactor*m_iMultiple)-1; i>=0; i--)
		if(m_Array){
			bEmpty = false;
			iIndex = i;
			break;
		}

	if(bEmpty)
		throw("Stack is empty!");

	value = m_Array[iIndex];
	
	if(iIndex == ((m_iGFactor*m_iMultiple)-m_iGFactor)){
		m_iMultiple--;
		m_Array = ResizeArray();
		//m_Array = ResizeArray(m_Array);
	} else {
		m_Array[iIndex] = NULL;
	}

	return value;
}

void CStack::Clear(void){

	m_iMultiple = 1;
	m_Array = ResizeArray();
	//m_Array = ResizeArray(m_Array);
	
	for(int i=0; i<m_iGFactor; i++)
		m_Array = NULL;

	return;
}

unsigned int CStack::Size(void){

	unsigned int iValid = m_iGFactor*m_iMultiple-m_iGFactor;
	for(unsigned int i=iValid; i<m_iGFactor*m_iMultiple; i++)
		if(m_Array)
			iValid++;
	return iValid;
}

unsigned int CStack::Capacity(void){
	return m_iGFactor*m_iMultiple;
}

Main.cpp --

#include "CStack.h"


int main(int argc, char** argv){

	CStack obj;

	cout << obj.Size() << " " << obj.Capacity() << endl;
	obj.Push(10.0).Push(5.3).Push(2.6);
	obj += 6.32;
	cout << obj.Size() << " " << obj.Capacity() << endl;
	cout << obj.Pop() << " "
		 << obj.Pop() << " "
		 << obj.Pop();
	cout << endl;
	obj.Push(3.4);
	obj.Clear();
	
	try{
		obj.Pop();
	}

	catch(const char* szString){
		cout << szString << endl;
	}

	return 0;
}

~~Johnathan~~LTM my new fad, know it, use it, love it, LAUGHING TO MYSELF
Advertisement
It looks like the array has been moved (or you are looking a the wrong address)
Could you post your code?

[Edit: -2.5301711256524607e-098 looks very close to 0 to me... :) ]

Cheers
Ooo, thats right, but my check depends on it being exactly zero not close to zero... how would I fix this? I've never come across this error before, usually if I made something 0 it would be exactly zero.

I also have tried using m_Array = 0.0 and that still does same thing.
~~Johnathan~~LTM my new fad, know it, use it, love it, LAUGHING TO MYSELF
In copy by reference constructor, you don't initalize it correctly. remove the if statement.

In assignment operator, it'd be better to delete the m_Array insted of callind the destructor. Remove the null-check also.

In ResizeArray function, remove the null-check.
Looking at your code, it seems to be that there are a couple of odd things going on. They may not be related to your problem though. Below is what I think you are trying to do (correct me if I am wrong) and why I think it is inappropriate:

1. You have a variable m_iGFactor that determines how much the stack grows by when pushing something onto the stack nessicitates a memory reallocation. The variable m_iMultiple stores how many m_iGFactors were allocated at last resize. You therefore calculate the maximum size of the stack with m_iGFactor * m_iMultiple. This is fine although strickly speaking m_iMultiple is not needed. The problem comes from the way you find where the top of the stack is (see 2).

2. You are assigning NULL to array elements to indicate that that portion of the stack is empty. You iterate back or forward over the array to find the first NULL element for pushing and last non-NULL element for popping, resizing if needed. The problem with this is two fold. Your array elements are not a pointer type but are doubles. In effect you store zero to indicate unused space, but what if you actually wanted to push zero onto the stack? Also, when you test if an array element is NULL, any non-zero value greater than zero but less than one (e.g 0.9) will also appear to be NULL since NULL is defined as 0 and the mantissa of the floating point number will be discarded for comparison. The second problem is that it is inefficient. You just need to store the top of the stack as an index into the array.

This is how I would change your code:

// CStack class#include <iostream>using namespace std;class CStack {public:    // Constructors    CStack(unsigned int iGFactor = 3);    CStack(CStack const &obj);    ~CStack(void);        // Operators    CStack& operator =(CStack const &rRHArg);    CStack& operator +=(double const value);    // Methods    CStack& Push(double const value);    double Pop(void);    void Clear(void);    unsigned int Size(void);    unsigned int Capacity(void);    private:    double* m_Array;    unsigned int m_iGFactor;    unsigned int m_iMultiple;    unsigned int stackTop;    protected:    double* ResizeArray(void);};CStack::CStack(unsigned int const iGFactor):m_iGFactor(iGFactor), m_iMultiple(2){    if(iGFactor==0)        throw("Invalid growth factor!");        m_Array = new double[iGFactor];        stackTop = 0;        for(int i=0; i<iGFactor; i++)        m_Array = 0.0;}CStack::CStack(CStack const &obj):m_iGFactor(obj.m_iGFactor),    m_iMultiple(obj.m_iMultiple), stackTop(obj.stackTop){    m_Array = new double[m_iGFactor*m_iMultiple];        for(unsigned int i=0; i <= stackTop; i++)        m_Array = obj.m_Array;}CStack::~CStack(void){    delete [] m_Array;}CStack& CStack::operator =(CStack const &rRHArg){    // for the expression a = b, a will be *this, and b will be rRHArg     if (&rRHArg != this)            // check for self assignment     {         delete [] m_Array;                m_iGFactor = rRHArg.m_iGFactor;        m_iMultiple = rRHArg.m_iMultiple;        stackTop = rRHArg.stackTop;                m_Array = new double[m_iGFactor*m_iMultiple];        for(unsigned int i=0; i < stackTop; i++)                m_Array = rRHArg.m_Array;    }     return *this;   //allows chaining of the = operator}CStack& CStack::Push(double const value){    if (stackTop == (m_iMultiple * m_iGFactor) - 1) {        m_iMultiple++;        m_Array = ResizeArray();    }    m_Array[stackTop] = value;    stackTop++;    return *this;}double* CStack::ResizeArray(){    double* NewArray = new double[m_iGFactor*m_iMultiple];    for(unsigned int i=0; i<(m_iGFactor*m_iMultiple); i++)            NewArray = m_Array;    delete [] m_Array;    return NewArray;}CStack& CStack::operator +=(double const value){    this->Push(value);    return *this;}double CStack::Pop(){    if(stackTop <= 0)        throw("Stack is empty!");    stackTop--;        if (stackTop < (m_iGFactor*m_iMultiple) - m_iGFactor) {        m_iMultiple--;        m_Array = ResizeArray();    }        return m_Array[stackTop];}void CStack::Clear(){    m_iMultiple = 1;    m_Array = ResizeArray();    stackTop = 0;        return;}unsigned int CStack::Size(){    return stackTop;}unsigned int CStack::Capacity(){    return (m_iGFactor*m_iMultiple);}
Haha You have made some good points, if the user wants to store 0.5 It wouldn't let them and you understood my code very well. Thanks for the help I'll try the changes you made, I'm surprised I never thought of doing it that way myself. I guess I'll remember, if you aren't actually using pointers don't check on NULL.

Again thanks for your help, I'll try it that way and hope to fix any bugs from there on.

Okay I've encountered another error, seems to be in my ResizeArray, when I go to delete m_Array it crashes the program and places me in one of those weird files pointing at a line that says it crashed the program haha. Is this because, again Im thinking them as pointers when really they are just an array? But an array is a pointer... hmm soo confusing lol.

The weird problem, is it seems to take me to the ostream file, when I try to delete m_Array, which for me is odd because that doesn't in my opinion have anything to do with ostream, just the cout's do!

Some more info, heres the exact error Im getting

Debug Error!
Program: ....programfilepath
DAMAGE: after Normal block (#54) at 0x00322F48



[Edited by - Surg AKA Kunark on August 3, 2005 8:39:39 AM]
~~Johnathan~~LTM my new fad, know it, use it, love it, LAUGHING TO MYSELF
Yay! I fixed my problem, the constructor had been changed to make the multiple go from 1 to 2, After changing it back the code worked just fine! W00t again thanks everyone for the help.
~~Johnathan~~LTM my new fad, know it, use it, love it, LAUGHING TO MYSELF
Okay, so my program has been going well, I've templatized it, and have some test code to try to make sure everything is working properly. And I've ran into a problem, I cant get char*'s to work. Because ofcourse you can't copy those like everything else. So heres my code so far... I'd love to hear any ones input.

// TStack class#include <iostream>using namespace std;template <typename T>class TStack {public:    // Constructors    TStack<T>(int iGFactor = 3);    TStack<T>(TStack<T> const &obj);    ~TStack<T>(void);        // Operators    TStack<T>& operator =(TStack<T> const &rRHArg);    TStack<T>& operator +=(T const value);	friend ostream& operator << <T>(ostream &rOut,  TStack<T> const &obj);	//ostream& operator <<(ostream &rOut)const;    // Methods    TStack<T>& Push(T const value);    T Pop(void);    void Clear(void);    unsigned int Size(void)const;    unsigned int Capacity(void)const;    private:	// Variables to hold information about the stack    T* m_Array;    unsigned int m_iGFactor;    unsigned int m_iMultiple;    unsigned int stackTop;    protected:	// Extra methods, protected!    T* ResizeArray(void);};template <typename T>TStack<T>::TStack<T>(int const iGFactor):m_iGFactor(iGFactor), m_iMultiple(1),											stackTop(0){	/*		The following checks the Growth Factor, if it is invalid then		throws an exception indicating that, otherwise it creates the 		array with an initial size of w/e was passed for the growth 		factor.	*/    if(iGFactor<= 0)        throw("Invalid growth factor!");        m_Array = new T[iGFactor];}template <typename T>TStack<T>::TStack<T>(TStack<T> const &obj):m_iGFactor(obj.m_iGFactor),    m_iMultiple(obj.m_iMultiple), stackTop(obj.stackTop){	/*		The following initializes the array to the appropriate size.		Then copies all the values from the obj array passed in, into 		this new array.	*/    m_Array = new T[m_iGFactor*m_iMultiple];        for(unsigned int i=0; i <= stackTop; i++)        m_Array = obj.m_Array;}template <typename T>TStack<T>::~TStack<T>(void){	// Deletes the array    delete [] m_Array;}template <typename T>TStack<T>& TStack<T>::operator =(TStack<T> const &rRHArg){    // for the expression a = b, a will be *this, and b will be rRHArg     if (&rRHArg != this)            // check for self assignment     { 		// Delete the array        this->~TStack<T>();        		// Copy over all the variables        m_iGFactor = rRHArg.m_iGFactor;        m_iMultiple = rRHArg.m_iMultiple;        stackTop = rRHArg.stackTop;        		// Initialize array and copy over data        m_Array = new T[m_iGFactor*m_iMultiple];        for(unsigned int i=0; i < stackTop; i++)                m_Array = rRHArg.m_Array;    }     return *this;   //allows chaining of the = operator}template <typename T>TStack<T>& TStack<T>::Push(T const value){	/*		If the array is full, increment multiples and		resize the array to the appropriate size.	*/    if (stackTop == (m_iMultiple * m_iGFactor)) {        m_iMultiple++;        m_Array = ResizeArray();    }	/*		Then, make the value passed in the current value		at the top of the stack, and increase the stack pointer.	*/    m_Array[stackTop] = value;    stackTop++;	// Return *this for chaining     return *this;}template <typename T>T* TStack<T>::ResizeArray(){	/*		Makes a new array, size calculated by factor to increase/decrease		by and iMultiple which indicates how many of those factors we 		should have.		Then copy over all the information from the previous array, and		delete the previous array	*/    T* NewArray = new T[m_iGFactor*m_iMultiple];    for(unsigned int i=0; i<(m_iGFactor*m_iMultiple); i++)            NewArray = m_Array;    delete [] m_Array;	// Return the new array    return NewArray;}//template < >//char* TStack<char*>::ResizeArray()//{//	/*//		Makes a new array, size calculated by factor to increase/decrease//		by and iMultiple which indicates how many of those factors we //		should have.////		Then copy over all the information from the previous array, and//		delete the previous array//	*///    char* NewArray = new char[m_iGFactor*m_iMultiple];//	for(unsigned int i=0; i<(m_iGFactor*m_iMultiple); i++){//		if(m_Array){//            NewArray = new char[strlen(m_Array)];//			strcpy(NewArray, m_Array);//		}else{//			NewArray = new char[0];//			NewArray = "";//		}//	}////	for(unsigned int i=0; i<(m_iGFactor*m_iMultiple); i++)//		if(m_Array)//			delete m_Array;//    delete [] m_Array;////	// Return the new array//    return NewArray;//}template <typename T>TStack<T>& TStack<T>::operator +=(T const value){	// Uses leveraging to add another value to array    this->Push(value);    return *this;}template <typename T>T TStack<T>::Pop(){	// Throw an exception if the stack is empty    if(stackTop <= 0)        throw("Stack is empty!");	// Decrement the stack counter    stackTop--;    	// If the array needs to be resized, do it    if (stackTop < (m_iGFactor*m_iMultiple) - m_iGFactor) {        m_iMultiple--;        m_Array = ResizeArray();    }    	// Return the value on top of the stack    return m_Array[stackTop];}template <typename T>void TStack<T>::Clear(){	/*		Resizes the array to initial size, sets multiple to 1		indicating it is initial size and places the stack counter		back to 0.	*/    m_iMultiple = 1;    m_Array = ResizeArray();    stackTop = 0;        return;}template <typename T>unsigned int TStack<T>::Size()const{	// Returns the index of the top of the stack	// This is the ammount of values on the stack    return stackTop;}template <typename T>unsigned int TStack<T>::Capacity()const{	// Returns how large array is	// This is calculated by Factor x Multiple    return (m_iGFactor*m_iMultiple);}template <typename T>ostream& operator << (ostream &rOut, TStack<T> const &obj){	for(int i=obj.stackTop-1; i>= 0; i--)		cout << obj.m_Array << endl;	return rOut;}


Okay I fixed my problem, decided to add an if statement to make sure something existed at the point before I copied it. Because with strings you get an unhandled exception without it.

[Edited by - Surg AKA Kunark on August 3, 2005 11:17:14 PM]
~~Johnathan~~LTM my new fad, know it, use it, love it, LAUGHING TO MYSELF
You do know that the standard library provides a templated "stack" (which is actually an "adapter" class; i.e. it wraps around another library container - without adding extra data - and provides a stack interface in terms of that container's interface) yes?

This topic is closed to new replies.

Advertisement