Sign in to follow this  
Surg AKA Kunark

Weird Problem

Recommended Posts

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[i] = 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[i])
			m_Array[i] = obj.m_Array[i];
		
}

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[i])
				m_Array[i] = rRHArg.m_Array[i];
	} 
	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[i]){
			bFull = false;
			m_Array[i] = 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[i])
//			NewArray[i] = array[i];
//		else
//			NewArray[i] = 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[i])
			NewArray[i] = m_Array[i];

	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[i]){
			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[i] = 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[i])
			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;
}

Share this post


Link to post
Share on other sites
ernow    732
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

Share this post


Link to post
Share on other sites
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[i] = 0.0 and that still does same thing.

Share this post


Link to post
Share on other sites
Ftn    462
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.

Share this post


Link to post
Share on other sites
Oralloy    154
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[i] = 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[i] = obj.m_Array[i];
}



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[i] = rRHArg.m_Array[i];
}
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[i] = m_Array[i];

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);
}


Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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[i] = obj.m_Array[i];
}


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[i] = rRHArg.m_Array[i];
}
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[i] = m_Array[i];

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[i]){
// NewArray[i] = new char[strlen(m_Array[i])];
// strcpy(NewArray[i], m_Array[i]);
// }else{
// NewArray[i] = new char[0];
// NewArray[i] = "";
// }
// }
//
// for(unsigned int i=0; i<(m_iGFactor*m_iMultiple); i++)
// if(m_Array[i])
// delete m_Array[i];
// 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[i] << 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]

Share this post


Link to post
Share on other sites
Zahlman    1682
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?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this