I have a class (DataBuffer) that has functions that return objects of DataBuffer but when I'm calling other class functions from within the function that returns the object of DataBuffer, the internal values are not being set after the function returns.

So, basically (if you made it through that first sentence), I have an initial DataBuffer that I need to perform various functions on and return new DataBuffers leaving the initial DataBuffer intact. The problem is that in one of the functions that operate on the original DataBuffer the DataBuffer that will be returned is not getting the correct values out of other functions within the DataBuffer class. Specifically setDimensions().

To the code!
DataBuffer.h

class DataException;

class DataBuffer
{
public:
   DataBuffer ();
   DataBuffer (const DataBuffer &rhs);
   DataBuffer (unsigned int width, unsigned int height, float fillValue=0.0)
      throw (DataException);

   void setDimensions (unsigned int width, unsigned int height, float fillValue=0.0)
      throw (DataException);

   DataBuffer func ();

protected:
   float **allocate (unsigned int width, unsigned int height)
      throw (DataException);
   unsigned int width;
   unsigned int height;
   float **buffer;
}

DataBuffer.cpp

DataBuffer::DataBuffer ()
   : width (0),
     height (0),
     buffer (NULL)
{
}

DataBuffer::DataBuffer (const DataBuffer &rhs)
   : width (rhs.width),
     height (rhs.height),
     buffer (rhs.buffer)
{
}

DataBuffer::DataBuffer (unsigned int width, unsigned int height, float *fillValue)
   throw (DataException)
{
   try
   {
      buffer = allocate (width, height);
   }
   catch (DataException &e)
   {
      e.addToStack ("DataBuffer::DataBuffer (unsigned int, unsigned int, float");

      throw e;
   }

   for (unsinged int i=0 ; i<height ; ++i)
   {
      for (unsigned int j=0 ; j<width ; ++j)
      {
         buffer[i][j] = fillValue;
      }
   }
}

void DataBuffer::setDimensions (unsigned int width, unsigned int height, float fillValue)
   throw (DataException)
{
   if ((width !=0) && (height != 0))
   {
      this->width = width;
      this->height = height;

      try
      {
         buffer = allocate (width, height);
      }
      catch (DataException &e)
      {
         e.addToStack ("DataBuffer::setDimensions()");

         throw e;
      }

      for (unsigned int i=0 ; i<height ; ++i)
      {
         for (unsigned int j=0 ; j<width ; ++j)
         {
            buffer[i][j] = fillValue;
         }
      }
   }
   else
   {
      throw DataException ("One of the dimensions is set to zero (0)", "DataBuffer::setDimensions()");
   }
}

float** DataBuffer::allocate (unsigned int width, unsigned int height)
   throw (DataException)
{
   float **result;

   ...

   return result;
}

DataBuffer DataBuffer::func ()
{
   DataBuffer result;

   try
   {
      result.setDimensions (this->width, this->height);
   }
   catch (DataException &e)
   {
      e.addToStack ("DataBuffer::func()");

      throw e;
   }

   ...

   return result;
}

My problem is that after calling setDimensions() in func() the values in result don't match what I passed in.

When I step into setDimensions() in the debugger (gdb) the values all get set properly but when it exits, the values in result are changed from what they were before setDimensions() but they aren't what was set in the function.

For example, when I'm debugging I stop at the return.setDimensions() call and step in to setDimensions() with values of width=500 and height=750. I can step through setDimensions() and everything looks fine but after stepping out of setDimensions() and looking at the values in result I see width=3000, height=0 and buffer is a different pointer.

I can't see anything wrong with what I'm doing but there is obviously something incorrect that I am missing . I would be greatly appreciated if someone could help me figure out what I'm doing wrong.

Unfortunately, I am not able to show the details of the allocate() function as it is a proprietary management scheme and the target system does not work with STL or templates so those aren't options. Also I am unable to use the encapsulation principles of c++ due to the extra milliseconds it takes for function calls, thus the values of width, height and buffer are public.

Thanks.

BTW, this is using g++ (GCC) 4.4.5 on Fedora 13

While it doesn't address your problem, you have a typo at line 15 (fillValue should just be a float, not a float*?), and a potential memory leak at line 48 (check whether buffer is non-NULL and if so free up the previously allocated memory before assigning a new chunk).

Personally, I dislike using the same names for method arguments and class members, as in setDimensions(), since the arguments mask the members and require the use of 'this->' to disambiguate. But that's just my preference.

Finally your constructor starting at line 15 also doesn't initialize the width and height members of the instance, possibly a logic error resulting from using the same names! ;)

I assume you're just testing something out, but func() would be better named newWithSameSize() or something else descriptive.

Now if I could just see what the problem with your new instance could be....

Sorry for the typos but I'm developing on a separate network computer that is not on the Internet.

While it doesn't address your problem, you have a typo at line 15 (fillValue should just be a float, not a float*?)

Correct. That was a typo, it is correct on my other computer.

Finally your constructor starting at line 15 also doesn't initialize the width and height members of the instance

Another typo, or more correctly omission. The initializers are there but I forgot to put them in. This is what the start of that constructor should look like:

DataBuffer::DataBuffer (unsigned int width, unsigned int height, float fillValue)
   throw (DataException)
   : width (width),
     height (height),
     buffer (NULL)
{

Thanks for taking a look. I appreciate any help I can get.

I'm having trouble following your code for some reason; I think it may be due to the lack of comments.

I noticed that your variable names aren't that great. I suspect that name/member/scope hiding is part of your problem. When you name a member function's local variables the same as a member variable, the local variable "hides" the member variable. I suggest you start by changing the names of your arguments in setDimensions from "width" and "height" to "newWidth" and "newHeight" respectively.

Also, where is your call to DataBuffer::func()? I suspect part of your problem is that you are calling func through a DataBuffer variable. This won't work because you are creating another DataBuffer object inside of func which is subsequently destroyed when func() ends.

You seem to have some sort of either nesting issue or circular issue going on; it's difficult to tell. Either way, the issue appears to be causing a scoping issue.

EDIT:
Oops, overlapped. I guess I should be a little quicker. :)

Edited 5 Years Ago by Fbody: n/a

I'm having trouble following your code for some reason; I think it may be due to the lack of comments.

I noticed that your variable names aren't that great. I suspect that name/member/scope hiding is part of your problem. When you name a member function's local variables the same as a member variable, the local variable "hides" the member variable. I suggest you start by changing the names of your arguments in setDimensions from "width" and "height" to "newWidth" and "newHeight" respectively.

Also, where is your call to DataBuffer::func()? I suspect part of your problem is that you are calling func through a DataBuffer variable. This won't work because you are creating another DataBuffer object inside of func which is subsequently destroyed when func() ends.

You seem to have some sort of either nesting issue or circular issue going on; it's difficult to tell. Either way, the issue appears to be causing a scoping issue.

EDIT:
Oops, overlapped. I guess I should be a little quicker. :)

One of the guys that I work with suggested changing the names as well so I'm going to change things around to ensure that there isn't a scoping issue and that what I'm trying to get it to do is what it does.

Thanks for the help. Hopefully this gets cleared up by coming up with more descriptive variable names.

Well, I tried to change the names of the variables as suggested to help clear up any confusion and I get the same results.

I had someone else look at it and by changing result to a DataBuffer* (and making the correct changes to func()) the values coming out of setDimensions() are now correct. Unfortunately one of my restrictions is that I can only use dynamically allocated space in a very controlled way and this violates those restrictions. It was mentioned that it appeared to be a stack problem from the compiler but I'm not sure how to adjust that with g++.

Care to elaborate on your restrictions? Maybe we can come up with a better solution.

Whatever the case may be, you're either going to have to use dynamic allocation or references to accomplish what you want to.

Turns out for the little bit of dynamic allocation needed to get this to work shouldn't be an issue with our system, yet.

I'm going to put the dynamic allocations in and revisit when we get to the target platform if there are issues with it.

Thanks for your help.

This article has been dead for over six months. Start a new discussion instead.