Have you ever had a problem where you are completely dumbfounded? Staring at the output of a program and saying this is impossible? Sort of like…

int a =5;
printf(“a=%d\n”,a);

Output:
A=6

Well, I’d appreciate if someone would take a look at this simple program below which creates a class Cbox that has just length, width, and height private double members, and a volume function to return the volume. Then I create an array of Cboxes named CArray. Oh, the Cbox class has a display() member function to output the three sides and the volume. That is important because that is where the screw up is occurring, i.e., when I try to call the display() function either on an individual Cbox object, or in a loop to dump all Cboxes from the array. Just to give you an idea of the kind of corruption I’m seeing before I show you the program, here is a little output:

m_Length = 2.000000       m_Width = 3.000000      m_Height = 1.000000     volume() = 2181932029977806200
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000
m_Length = 2.200000       m_Width = 1.000000      m_Height = 0.500000     volume() = 1200062616487793500
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000
m_Length = 0.200000       m_Width = 3.500000      m_Height = 2.000000     volume() = 4363864059955613000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0000
m_Length = 0.300000       m_Width = 3.000000      m_Height = 3.000000     volume() = 9818694133995429100
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0000
[/CODE=C++]

I think you get the idea.

I’ve run this program on two different computers using three different compilers/development environments, i.e., Microsoft Visual C++ 6.0, Dev C++, and the new CodeBlocks.  The program works perfectly in Dev C++ and CodeBlocks, but screws up badly in VC++.  Its almost like it can’t handle four %f format specifiers in a row.  
The output should look like this…

[CODE=C++]
CArray() Constructor Called!
2.000000        3.000000        1.000000        6.000000
2.200000        1.000000        0.500000        1.100000
0.200000        3.500000        2.000000        1.400000
0.300000        3.000000        3.000000        2.700000


2.000000        3.000000        1.000000        6.000000
2.200000        1.000000        0.500000        1.100000
0.200000        3.500000        2.000000        1.400000
0.300000        3.000000        3.000000        2.700000
[/CODE=C++]

Here is the program.  Could somebody run it and see what they get, and if it screws up give me an idea what’s wrong (it’s a really short, simple program)?  

[CODE=C++]
#include <stdio.h>
#define  MAX_SIZE    5

class CBox
{
 public:
 CBox(double lv=1.0, double wv=1.0, double hv=1.0)
 :m_Length(lv), m_Width(wv), m_Height(hv)
 {
  //printf("CBox() Constructor Called!\n");
 }

 ~CBox()
 {
  //printf("~CBox() Destructor Called!\n");
 }

 void SetLength(double ln)
 {
  this->m_Length=ln;
 }

 void SetWidth(double wd)
 {
  this->m_Width=wd;
 }

 void SetHeight(double ht)
 {
  this->m_Height=ht;
 }

 double volume(void)
 {
  return this->m_Length * this->m_Width * this->m_Height;
 }

 void display(void)
 {
  printf("%f\t%f\t%f\t%f\n",m_Length,m_Width,m_Height,volume());
 }

 private:
 double m_Length;
 double m_Width;
 double m_Height;
};


class CArray
{
 public:
 CArray()
 {
  printf("CArray() Constructor Called!\n");
  m_New=0;
 }

 ~CArray()
 {
  printf("CArray() Destructor Called!\n");
 }

 void add(CBox& box)
 {
  if(m_New<MAX_SIZE)
  {
     bx[m_New]=box;
     m_New++;
  }
 }

 void dump(void)
 {
  unsigned int i;
  for(i=0;i<m_New;i++)
      bx[i].display();
 }

 private:
 CBox bx[MAX_SIZE];
 unsigned int m_New;
};


int main(void)
{
 unsigned int i;
 CArray arr;
 CBox bx[4];

 bx[0].SetHeight(1.0F), bx[0].SetLength(2.0F), bx[0].SetWidth(3.0F);
 bx[1].SetHeight(0.5F), bx[1].SetLength(2.2F), bx[1].SetWidth(1.0F);
 bx[2].SetHeight(2.0F), bx[2].SetLength(0.2F), bx[2].SetWidth(3.5F);
 bx[3].SetHeight(3.0F), bx[3].SetLength(0.3F), bx[3].SetWidth(3.0F);
 for(i=0;i<4;i++)
 {
     arr.add(bx[i]);
     bx[i].display();
 }
 printf("\n\n");
 arr.dump();
 getchar();

 return 0;
}

Obviously, the presented output was printed by another (version of) program (no member names in this snippet printf).
Of course, VC++ 6.0 is too old compiler but I have worked with it many years and never have troubles with printf...

Try to replace printf to cout << and see what happens...

Hi ArkM!

 Here's the result from couts (took me a minute or two to think how to do it):

2       3       1       6
2.2     1       0.5     1.1
0.2     3.5     2       1.4
0.3     3       3       2.7


2       3       1       6
2.2     1       0.5     1.1
0.2     3.5     2       1.4
0.3     3       3       2.7
Press any key to continue

That is correct output.

I've lots of versions of that program - been fooling with it all afternoon in disbelief of what I'm seeing. The first output I presented was typical. Never thought to try couts as I never use that library. I actually hate it.

I'm really beginning to think its a VC++ bug. I'll play with it somemore but can't imagine what's going on. I'm actually not a beginner - however I do make stupid mistakes more frequently than I'd like - and perhaps there's one in my code. Its just about too much to believe there is a bug in VC++ - its too good a compiler.

May be your VC++ 6.0 installation was not patched properly (upto Service Pack 6 or 5, I don't remember now). In actual fact there were errors in VC++ 6.0 but as usually I have found some workarounds...

Apropos, a possible reason of the strange output:

printf("%f\t%f\t%f\t%f\n",m_Length,m_Width,m_Height,volume);
// () missed after volume

It's impossible to detect this error in compile time. That's why awkward C++ streams are better than old good printf ;)

commented: thanks! +1

Hi Again ArkM!

I've basically moved on. I was thinking of seeing what would happen using the Win32 Console output functions; but there too it would be necessary to use something or other from the printf family of functions such as sprintf or whatever to write a variable's output to a buffer for console output with WriteConsole().

In terms of the missing () from volume() you mentioned above; that had no effect as I had tried it too. Believe it or not, what would solve the problem was eliminating that last variable from the printf function and just ending the format string with a \t instead of \n and outputing the this->volume() with a seperate printf. The output of course (the correct one) would be the same. Observations such as this led me to believe my code was OK and the problem was a VC++ thing.

I'm actually working on templates, and that's where I encountered the problem. Since I'm not sure of what I'm doing there yet I figured I was making some sort of template related mistake, but couldn't find it. That's when I created the code I posted without any templates and the problem still couldn't be eliminated (with VC++). I changed the variable declarations to ints and that eliminated the problem. Below is the same code with templates and it works fine.

I'm using VC++ 6 because I want to learn ATL and I don't have a newer version of it. I know MS has 'express' versions for free, but I'm trying to coax a license out of our IT dept for the high octane version.

working example

#include <stdio.h>   //template13
#define  MAX_SIZE    5

class CBox
{
 public:
 CBox(int lv=1.0, int wv=1.0, int hv=1.0):m_Length(lv), m_Width(wv), m_Height(hv)
 {
  //printf("CBox() Constructor Called!\n");
 }


 ~CBox()
 {
  //printf("~CBox() Destructor Called!\n");
 }

 
 void SetLength(int ln)   //program shows syntax of templates and passing template
 {                        //as parameter to function (see AddData).  Also shows
  this->m_Length=ln;      //how to set up template members when they are not inline.
 }


 void SetWidth(int wd)
 {
  this->m_Width=wd;
 }


 void SetHeight(int ht)
 {
  this->m_Height=ht;
 }


 int volume(void)
 {
  return this->m_Length * this->m_Width * this->m_Height;
 }

  
 void display(void)
 {
  printf("%d\t%d\t%d\t%d\n",m_Length,m_Width,m_Height,volume());
 }


 private:
 int m_Length;
 int m_Width;
 int m_Height;
};



template <typename type, unsigned int iSize> class CArray
{
 public:
 CArray(); 
 ~CArray();
 bool add(type&);
 unsigned int get_size(void) const;
 void dump(void);

 private:
 unsigned int m_New;
 type x[iSize];
};


template <typename type, unsigned int iSize> CArray<type,iSize>::CArray() 
{
  puts("CArray() Constructor Called!");
  m_New=0;
}


template <typename type, unsigned int iSize> CArray<type,iSize>::~CArray() 
{
  puts("Destructor Called!");
}


template<class type, unsigned int iSize> bool CArray<type,iSize>::add(type& pObj)
{
 if(this->m_New<iSize)
 {
    x[m_New++]=pObj;
    return true;
 }

 return false;
}


template<class type, unsigned int iSize> unsigned int CArray<type,iSize>::get_size(void) const
{
 return this->m_New;
}


template<class type, unsigned int iSize> void CArray<type,iSize>::dump(void)
{
 unsigned int i;

 printf("\t\t\t&bx[i]\t\tLen\twidth\theight\tvolume()\n");
 printf("========================================================================\n");
 for(i=0;i<m_New;i++)
 {
     printf("\t\t\t%u\t\t",&x[i]);
     x[i].display();
 }
 printf("\n\n");
}


template<typename type, unsigned int iSize> void AddData(CBox bx[], CArray<type,iSize>& ar)
{
 bx[0].SetHeight(1),  bx[0].SetLength(2),  bx[0].SetWidth(3);
 bx[1].SetHeight(5),  bx[1].SetLength(2),  bx[1].SetWidth(1);
 bx[2].SetHeight(2),  bx[2].SetLength(2),  bx[2].SetWidth(3);
 bx[3].SetHeight(3),  bx[3].SetLength(3),  bx[3].SetWidth(3);
}


int main(void)
{ 
 CArray<CBox,4> arr;
 unsigned int i;
 CBox bx[4];
 
 AddData(bx,arr);
 printf("sizeof(bx[0]) = %u\n",sizeof(bx[0]));
 printf("\n\n");
 printf("i\tarr.add(bx[i])\t&bx[i]\t\tLen\twidth\theight\tvolume()\n");
 printf("========================================================================\n");
 for(i=0;i<4;i++)
 {
     printf("%u\t%u\t\t%u\t\t",i,arr.add(bx[i]),&bx[i]);
     bx[i].display();
 }
 printf("\n\n");
 arr.dump();
     
 return 0;
}

/*
CArray() Constructor Called!
sizeof(bx[0]) = 12


i       arr.add(bx[i])  &bx[i]          Len     width   height  volume()
========================================================================
0       1               1244948         2       3       1       6
1       1               1244960         2       1       5       10
2       1               1244972         2       3       2       12
3       1               1244984         3       3       3       27


                        &bx[i]          Len     width   height  volume()
========================================================================
                        1245000         2       3       1       6
                        1245012         2       1       5       10
                        1245024         2       3       2       12
                        1245036         3       3       3       27

Destructor Called!
*/

Thanks a lot for your help and looking at it!

Fred

Well, post your template troubles next time ;)

Try to part with old good VC++ 6.0 as soon as possible. Probably the best choice is VC++ 2008 Pro (try to get additional MSDN license at the same time).

Good luck!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.