Problem with class type in static instance of struct

Discussion in 'C++' started by Robert Sturzenegger, Dec 27, 2004.

  1. We had a strange problem in a large project with the use of a string class
    in a static instance of a struct.
    I managed to reproduce the exactly same problem in a very short program (see
    below).
    When the constant SHORT_STRING_SIZE_LIMIT is set to 0, the program works as
    expected and outputs the string "+". When it is set to 7, it outputs garbage
    (a part of a non-initialized storage area).
    We are using gcc version 3.3 on SuSE Linux.

    #include <iostream>
    using namespace std;

    const unsigned int SHORT_STRING_SIZE_LIMIT = 0;
    //const unsigned int SHORT_STRING_SIZE_LIMIT = 7;


    // String
    class ----------------------------------------------------------------
    class String
    {
    public:
    String(const char* s);
    friend ostream& operator<< (ostream& os, const String& sStr);

    private:
    char* allocate();

    char m_cShortString[SHORT_STRING_SIZE_LIMIT + 1];
    unsigned int m_uiCapa;
    unsigned int m_uiSize;
    char* m_p;
    };

    String::String(const char* s)
    {
    if (s == NULL) {
    m_p = allocate();
    m_p[0] = '\0';
    return;
    }
    m_uiSize = strlen(s);
    m_p = allocate();
    strcpy(m_p, s);
    }

    char* String::allocate()
    {
    char* p;
    if (m_uiSize <= SHORT_STRING_SIZE_LIMIT) {
    m_uiCapa = SHORT_STRING_SIZE_LIMIT;
    p = m_cShortString;
    } else {
    m_uiCapa = m_uiSize;
    p = new char[m_uiCapa + 1];
    }
    return p;
    }

    ostream& operator<< (ostream& os, const String& sStr)
    {
    os << sStr.m_p;
    return os;
    }
    // End of String
    class ---------------------------------------------------------


    struct Operators
    {
    String m_sOperator;
    };
    static Operators operators= {"+"};


    int main()
    {
    cout << operators.m_sOperator << endl;
    }
    Robert Sturzenegger, Dec 27, 2004
    #1
    1. Advertising

  2. Robert Sturzenegger wrote:
    > We had a strange problem in a large project with the use of a string class
    > in a static instance of a struct.
    > I managed to reproduce the exactly same problem in a very short program (see
    > below).
    > When the constant SHORT_STRING_SIZE_LIMIT is set to 0, the program works as
    > expected and outputs the string "+". When it is set to 7, it outputs garbage
    > (a part of a non-initialized storage area).
    > We are using gcc version 3.3 on SuSE Linux.


    Well, looks like a bug in the compiler. Did you use the debugger to find
    out what's wrong?

    > [...]


    V
    Victor Bazarov, Dec 27, 2004
    #2
    1. Advertising

  3. Robert Sturzenegger

    Alan Guest

    "Robert Sturzenegger" <> wrote in message news:cqpdrr$1hh$...
    > We had a strange problem in a large project with the use of a string class
    > in a static instance of a struct.
    > I managed to reproduce the exactly same problem in a very short program (see
    > below).
    > When the constant SHORT_STRING_SIZE_LIMIT is set to 0, the program works as
    > expected and outputs the string "+". When it is set to 7, it outputs garbage
    > (a part of a non-initialized storage area).
    > We are using gcc version 3.3 on SuSE Linux.
    >
    > #include <iostream>
    > using namespace std;
    >
    > const unsigned int SHORT_STRING_SIZE_LIMIT = 0;
    > file://const unsigned int SHORT_STRING_SIZE_LIMIT = 7;
    >
    >
    > // String
    > class ----------------------------------------------------------------
    > class String
    > {
    > public:
    > String(const char* s);
    > friend ostream& operator<< (ostream& os, const String& sStr);
    >
    > private:
    > char* allocate();
    >
    > char m_cShortString[SHORT_STRING_SIZE_LIMIT + 1];
    > unsigned int m_uiCapa;
    > unsigned int m_uiSize;
    > char* m_p;
    > };
    >
    > String::String(const char* s)
    > {
    > if (s == NULL) {
    > m_p = allocate();
    > m_p[0] = '\0';
    > return;
    > }
    > m_uiSize = strlen(s);
    > m_p = allocate();
    > strcpy(m_p, s);
    > }
    >
    > char* String::allocate()
    > {
    > char* p;
    > if (m_uiSize <= SHORT_STRING_SIZE_LIMIT) {
    > m_uiCapa = SHORT_STRING_SIZE_LIMIT;
    > p = m_cShortString;
    > } else {
    > m_uiCapa = m_uiSize;
    > p = new char[m_uiCapa + 1];
    > }
    > return p;
    > }
    >
    > ostream& operator<< (ostream& os, const String& sStr)
    > {
    > os << sStr.m_p;
    > return os;
    > }
    > // End of String
    > class ---------------------------------------------------------
    >
    >
    > struct Operators
    > {
    > String m_sOperator;
    > };
    > static Operators operators= {"+"};
    >
    >
    > int main()
    > {
    > cout << operators.m_sOperator << endl;
    > }
    >
    >


    I had no problems with this program using
    DigitalMars (have purchased CD) in Win2K
    Pro SP4 - in both cases the output is "+"

    Alan
    Alan, Dec 27, 2004
    #3
  4. Robert Sturzenegger

    jd Guest

    Le Mon, 27 Dec 2004 17:39:24 +0100, Robert Sturzenegger a écrit :

    > We had a strange problem in a large project with the use of a string class
    > in a static instance of a struct.
    > I managed to reproduce the exactly same problem in a very short program (see
    > below).
    > When the constant SHORT_STRING_SIZE_LIMIT is set to 0, the program works as
    > expected and outputs the string "+". When it is set to 7, it outputs garbage
    > (a part of a non-initialized storage area).
    > We are using gcc version 3.3 on SuSE Linux.
    >
    > #include <iostream>
    > using namespace std;
    >
    > const unsigned int SHORT_STRING_SIZE_LIMIT = 0;
    > //const unsigned int SHORT_STRING_SIZE_LIMIT = 7;
    >
    >
    > // String
    > class ----------------------------------------------------------------
    > class String
    > {
    > public:
    > String(const char* s);
    > friend ostream& operator<< (ostream& os, const String& sStr);
    >
    > private:
    > char* allocate();
    >
    > char m_cShortString[SHORT_STRING_SIZE_LIMIT + 1];
    > unsigned int m_uiCapa;
    > unsigned int m_uiSize;
    > char* m_p;
    > };
    >
    > String::String(const char* s)
    > {
    > if (s == NULL) {
    > m_p = allocate();
    > m_p[0] = '\0';
    > return;
    > }
    > m_uiSize = strlen(s);
    > m_p = allocate();
    > strcpy(m_p, s);
    > }
    >
    > char* String::allocate()
    > {
    > char* p;
    > if (m_uiSize <= SHORT_STRING_SIZE_LIMIT) {
    > m_uiCapa = SHORT_STRING_SIZE_LIMIT;
    > p = m_cShortString;
    > } else {
    > m_uiCapa = m_uiSize;
    > p = new char[m_uiCapa + 1];
    > }
    > return p;
    > }
    >
    > ostream& operator<< (ostream& os, const String& sStr)
    > {
    > os << sStr.m_p;
    > return os;
    > }
    > // End of String
    > class ---------------------------------------------------------
    >
    >
    > struct Operators
    > {
    > String m_sOperator;
    > };
    > static Operators operators= {"+"};
    >
    >
    > int main()
    > {
    > cout << operators.m_sOperator << endl;
    > }


    This doesn't look a compiler error for me.
    Your Operators struct simply doesn't use the constructors you have
    providen for your String class.
    jd, Dec 27, 2004
    #4
  5. Robert Sturzenegger

    Ron Natalie Guest

    Robert Sturzenegger wrote:
    > We had a strange problem in a large project with the use of a string class
    > in a static instance of a struct.
    > I managed to reproduce the exactly same problem in a very short program (see
    > below).
    > When the constant SHORT_STRING_SIZE_LIMIT is set to 0, the program works as


    Your class needs a copy constructor (and a assignment operator and a destructor,
    and perhaps even a default constructor).

    The problem is that when the limit is set to zero, the implicitly defined
    copy constructor copies the pointer but since it points to memory you never
    free, the thing works OK. In your case where you have the small string
    support, the pointer is copied, but it points to the array of a temporary
    object whose lifetime expires (and obviously gets written over).
    Ron Natalie, Dec 27, 2004
    #5
  6. Robert Sturzenegger

    Muk Guest

    strcpy(m_p, s);

    Before you do this make sure the src string s is null terminated (\0).
    In your case it looks like it is not ("+"). Now when
    SHORT_STRING_SIZE_LIMIT = 7, you are copying into char
    m_cShortString[8]; Since the dest array m_cShortString may not have \0
    at each index, the string is basically not null terminated. This may
    cause os << sStr.m_p to print vague results since it does not know the
    end of the array (no \0 at end). Make sure all your arrays and strings
    are null terminated, especially when using C style functions like
    strcpy. When SHORT_STRING_SIZE_LIMIT = 0 you are creating new
    allocation using new char[m_uiCapa + 1] and it looks like the resultant
    memory had nulls in it and hence it worked.
    Muk, Dec 28, 2004
    #6
  7. "Muk" <> wrote...
    > strcpy(m_p, s);
    >
    > Before you do this make sure the src string s is null terminated (\0).
    > In your case it looks like it is not ("+"). [...]


    Every string literal is null-terminated, see 2.13.4p4.
    Victor Bazarov, Dec 28, 2004
    #7
  8. "Ron Natalie" <> wrote in message
    news:41d08e8f$0$30427$...
    > Robert Sturzenegger wrote:
    > > We had a strange problem in a large project with the use of a string
    > > class
    > > in a static instance of a struct.
    > > I managed to reproduce the exactly same problem in a very short program
    > > (see
    > > below).
    > > When the constant SHORT_STRING_SIZE_LIMIT is set to 0, the program works
    > > as

    >
    > Your class needs a copy constructor (and a assignment operator and a
    > destructor,
    > and perhaps even a default constructor).
    >
    > The problem is that when the limit is set to zero, the implicitly defined
    > copy constructor copies the pointer but since it points to memory you
    > never
    > free, the thing works OK. In your case where you have the small string
    > support, the pointer is copied, but it points to the array of a temporary
    > object whose lifetime expires (and obviously gets written over).
    >


    What I posted, is only a small extract of the class. As a matter of course
    the class does have a default ctor, several other ctors, a copy ctor and a
    dtor. But these do not affect the behaviour in question and that's why I
    leaved them out.
    Robert Sturzenegger, Dec 28, 2004
    #8
  9. "jd" <> schrieb im Newsbeitrag
    news:p...
    > Le Mon, 27 Dec 2004 17:39:24 +0100, Robert Sturzenegger a écrit :
    >
    > > We had a strange problem in a large project with the use of a string

    class
    > > in a static instance of a struct.
    > > I managed to reproduce the exactly same problem in a very short program

    (see
    > > below).
    > > When the constant SHORT_STRING_SIZE_LIMIT is set to 0, the program works

    as
    > > expected and outputs the string "+". When it is set to 7, it outputs

    garbage
    > > (a part of a non-initialized storage area).
    > > We are using gcc version 3.3 on SuSE Linux.
    > >
    > > #include <iostream>
    > > using namespace std;
    > >
    > > const unsigned int SHORT_STRING_SIZE_LIMIT = 0;
    > > //const unsigned int SHORT_STRING_SIZE_LIMIT = 7;
    > >
    > >
    > > // String
    > > class ----------------------------------------------------------------
    > > class String
    > > {
    > > public:
    > > String(const char* s);
    > > friend ostream& operator<< (ostream& os, const String& sStr);
    > >
    > > private:
    > > char* allocate();
    > >
    > > char m_cShortString[SHORT_STRING_SIZE_LIMIT + 1];
    > > unsigned int m_uiCapa;
    > > unsigned int m_uiSize;
    > > char* m_p;
    > > };
    > >
    > > String::String(const char* s)
    > > {
    > > if (s == NULL) {
    > > m_p = allocate();
    > > m_p[0] = '\0';
    > > return;
    > > }
    > > m_uiSize = strlen(s);
    > > m_p = allocate();
    > > strcpy(m_p, s);
    > > }
    > >
    > > char* String::allocate()
    > > {
    > > char* p;
    > > if (m_uiSize <= SHORT_STRING_SIZE_LIMIT) {
    > > m_uiCapa = SHORT_STRING_SIZE_LIMIT;
    > > p = m_cShortString;
    > > } else {
    > > m_uiCapa = m_uiSize;
    > > p = new char[m_uiCapa + 1];
    > > }
    > > return p;
    > > }
    > >
    > > ostream& operator<< (ostream& os, const String& sStr)
    > > {
    > > os << sStr.m_p;
    > > return os;
    > > }
    > > // End of String
    > > class ---------------------------------------------------------
    > >
    > >
    > > struct Operators
    > > {
    > > String m_sOperator;
    > > };
    > > static Operators operators= {"+"};
    > >
    > >
    > > int main()
    > > {
    > > cout << operators.m_sOperator << endl;
    > > }

    >
    > This doesn't look a compiler error for me.
    > Your Operators struct simply doesn't use the constructors you have
    > providen for your String class.
    >


    Yes, it does! I also tried with cout in the ctor. The ctor is run in both
    cases.
    Robert Sturzenegger, Dec 28, 2004
    #9
  10. Robert Sturzenegger

    Ron Natalie Guest

    Robert Sturzenegger wrote:

    >
    >
    > What I posted, is only a small extract of the class. As a matter of course
    > the class does have a default ctor, several other ctors, a copy ctor and a
    > dtor. But these do not affect the behaviour in question and that's why I
    > leaved them out.
    >
    >

    Perhaps you should put them back in, because it sure as hell makes the
    example WRONG without them.

    What does your copy constructor look like?
    Ron Natalie, Dec 28, 2004
    #10
  11. Ron Natalie wrote:
    > Robert Sturzenegger wrote:
    >
    >>
    >>
    >> What I posted, is only a small extract of the class. As a matter of
    >> course the class does have a default ctor, several other ctors, a copy
    >> ctor and a dtor. But these do not affect the behaviour in question and
    >> that's why I leaved them out.
    >>
    >>

    > Perhaps you should put them back in, because it sure as hell makes the
    > example WRONG without them.


    Why is it WRONG? We're not discussing the merits of dynamic memory
    allocation and the rule of three here. Is there any part to the code
    presented that exhibits undefined behaviour? If yes, would you please
    elaborate?

    > What does your copy constructor look like?


    Why do you care? There is no d-tor that attempts to delete the pointer.
    There is no copying taking place in this code, AFAICS. Or is there?
    The question is about the code posted. It _is_ complete and is known
    to exhibit the behaviour described, but only when compiled with g++
    (I did check with VC++, and it worked as expected). Why does it matter
    what the _other_ code looks like?
    Victor Bazarov, Dec 28, 2004
    #11
  12. "Ron Natalie" <> schrieb im Newsbeitrag
    news:41d1703b$0$30445$...
    > Robert Sturzenegger wrote:
    >
    > >
    > >
    > > What I posted, is only a small extract of the class. As a matter of

    course
    > > the class does have a default ctor, several other ctors, a copy ctor and

    a
    > > dtor. But these do not affect the behaviour in question and that's why I
    > > leaved them out.
    > >
    > >

    > Perhaps you should put them back in, because it sure as hell makes the
    > example WRONG without them.
    >
    > What does your copy constructor look like?


    Would you prefer to see 3786 lines of code here. As I said, this sample code
    is about the minumum which is necessary, to show the behavior in question.
    Every bit of code NOT shown here does NOT affect this behaviour.
    In the meantime, I rather think that what is missing, are ctors and copy
    ctor of the struct.
    Robert Sturzenegger, Dec 28, 2004
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Chris Fogelklou
    Replies:
    36
    Views:
    1,345
    Chris Fogelklou
    Apr 20, 2004
  2. Sridhar R
    Replies:
    14
    Views:
    1,380
    =?iso-8859-1?Q?Fran=E7ois?= Pinard
    Feb 10, 2004
  3. dutchgoldtony
    Replies:
    15
    Views:
    462
    Mike Wahler
    Nov 16, 2005
  4. Replies:
    2
    Views:
    722
    David Harmon
    Sep 20, 2006
  5. Martin P. Hellwig
    Replies:
    1
    Views:
    362
    Martin P. Hellwig
    Mar 26, 2010
Loading...

Share This Page