Thread: Creating a dynamic array of char

  1. #1
    Registered User Sharke's Avatar
    Join Date
    Jun 2008
    Location
    NYC
    Posts
    303

    Creating a dynamic array of char

    I've been implementing a simplified string class for a series of exercises. I'm asked to add a c_string() function, so I have this experimental member function:

    Code:
        char *c_string() {
            if(c_str) delete c_str;
            char *c_str = new char;
            char *temp = c_str;
            for (size_type i = 0; i < data.size(); i++)
                *(temp++) = data[i];
            *temp = '\0';
            return c_str;
        }
    What's confusing me is that the program works even though I don't specify a size for the array of char (I know I should btw!). I'm able to write to the new char and beyond without any complaints or crashes, as long as the text is only two or three words. Any more than this and I get a bad alloc message and it crashes. Is it that I'm allowed to keep writing to successive addresses until I hit memory that's already allocated? I didn't think you were allowed to write to memory unless it was specifically allocated in full.

  2. #2
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    > I didn't think you were allowed to write to memory unless it was specifically allocated in full.
    Well it may be allocated to you elsewhere, or as "extra" for you, or to someone, or to no one.

    Just allocate the size of the array to data.size() + 1 and be done with it. Also make sure you save the pointer that comes back from new, which you are not doing in this case. Otherwise you have a memory leak.

    To make it compatible with c_str() you could make it const char * :-). But just a thought.

  3. #3
    Registered User Sharke's Avatar
    Join Date
    Jun 2008
    Location
    NYC
    Posts
    303
    I originally sized the array with size() + 1, I just took it out to see what would happen. The pointer c_str is a member of my class, so it's saved. I don't know why I redeclared it as a char*, an oversight. Thanks for pointing out the need for constness by the way!
    Last edited by Sharke; 06-22-2009 at 01:00 AM.

  4. #4
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    > The pointer c_str is a member of my class, so it's saved. I don't know why I redeclared it as a char*, an oversight.
    A deadly one at that too

    That's why it pays to have a naming scheme for member variables, ie append underscore for private members, or prepend with "m_" or something.

  5. #5
    Registered User Sharke's Avatar
    Join Date
    Jun 2008
    Location
    NYC
    Posts
    303
    Quote Originally Posted by zacs7 View Post
    > The pointer c_str is a member of my class, so it's saved. I don't know why I redeclared it as a char*, an oversight.
    A deadly one at that too

    That's why it pays to have a naming scheme for member variables, ie append underscore for private members, or prepend with "m_" or something.
    I guess you're probably right, I just haven't really settled upon a consistent system of naming things yet. I'm still pretty much all over the place

  6. #6
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> Is it that I'm allowed to keep writing to successive addresses until I hit memory that's already allocated?

    No, of course not. Accessing even a single byte outside of what you allocated is undefined behavior and incorrect.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  7. #7
    Registered User Sharke's Avatar
    Join Date
    Jun 2008
    Location
    NYC
    Posts
    303
    Quote Originally Posted by Sebastiani View Post
    >> Is it that I'm allowed to keep writing to successive addresses until I hit memory that's already allocated?

    No, of course not. Accessing even a single byte outside of what you allocated is undefined behavior and incorrect.
    I realize that it's "incorrect," but my point was that I wasn't actually given an error message until the string I laid down at that address was over a certain length. Two or three words went past unnoticed, but any more and I got a bad allocation error. I was just surprised because I had expected the program to puke as soon as I accessed one byte past the one I'd allocated.

  8. #8
    int x = *((int *) NULL); Cactus_Hugger's Avatar
    Join Date
    Jul 2003
    Location
    Banks of the River Styx
    Posts
    902
    I realize that it's "incorrect," but my point was that I wasn't actually given an error message until the string I laid down at that address was over a certain length. Two or three words went past unnoticed, but any more and I got a bad allocation error. I was just surprised because I had expected the program to puke as soon as I accessed one byte past the one I'd allocated.
    Just because it didn't puke for you doesn't mean it won't on my machine, etc. That's the nature of undefined behaviour: it's undefined.
    long time; /* know C? */
    Unprecedented performance: Nothing ever ran this slow before.
    Any sufficiently advanced bug is indistinguishable from a feature.
    Real Programmers confuse Halloween and Christmas, because dec 25 == oct 31.
    The best way to accelerate an IBM is at 9.8 m/s/s.
    recursion (re - cur' - zhun) n. 1. (see recursion)

  9. #9
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> I realize that it's "incorrect," but my point was that I wasn't actually given an error message until the string I laid down at that address was over a certain length.

    Well, typically, you're only going to get an error message if you try to access a memory address outside of the range(s) allowed to your program by the operating system. This is sometimes indirect, of course, as you might corrupt an area within your own stack, say, in effect overwriting the return address of a function, for instance.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  10. #10
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by Sebastiani View Post
    Well, typically, you're only going to get an error message if you try to access a memory address outside of the range(s) allowed to your program by the operating system. This is sometimes indirect, of course, as you might corrupt an area within your own stack, say, in effect overwriting the return address of a function, for instance.
    Yeah, those bugs are always loads of fun to track down...
    "I am probably the laziest programmer on the planet, a fact with which anyone who has ever seen my code will agree." - esbo, 11/15/2008

    "the internet is a scary place to be thats why i dont use it much." - billet, 03/17/2010

  11. #11
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by Sharke View Post
    What's confusing me is that the program works even though I don't specify a size for the array of char
    The last time I played Russian Roulette, I didn't die. It was very confusing.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  12. #12
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by cpjust View Post
    Yeah, those bugs are always loads of fun to track down...
    If you mean "easy to track down," then I agree. It's always easy when the stupid thing crashes. The hard problems are when it DOESN'T crash, but gives subtly wrong answers.

    EDIT: Okay, I guess I should define what I mean by "easy." The last random crash I dealt with was an assertion trigger (call to assert() failed and crashed the code, only in debug mode, of course). It took about 2 weeks to find the problem. That was borderline easy. The hard problems take months to find.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  13. #13
    Banned ಠ_ಠ's Avatar
    Join Date
    Mar 2009
    Posts
    687
    Quote Originally Posted by brewbuck View Post
    If you mean "easy to track down," then I agree. It's always easy when the stupid thing crashes. The hard problems are when it DOESN'T crash, but gives subtly wrong answers.
    in my C class we used a compiler that, when I *accidentally* deferenced a misallocated pointer, gave me the "Done!" that it usually does when a program finishes successfully
    Last edited by ಠ_ಠ; 06-23-2009 at 12:28 AM.
    ╔╗╔══╦╗
    ║║║╔╗║║
    ║╚╣╚╝║╚╗
    ╚═╩══╩═╝

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Profiler Valgrind
    By afflictedd2 in forum C++ Programming
    Replies: 4
    Last Post: 07-18-2008, 09:38 AM
  2. nebie simply needs help creating 2 dimensional char array
    By MegaManZZ in forum C++ Programming
    Replies: 13
    Last Post: 01-14-2008, 10:13 AM
  3. linked list inside array of structs- Syntax question
    By rasmith1955 in forum C Programming
    Replies: 14
    Last Post: 02-28-2005, 05:16 PM
  4. comparing fields in a text file
    By darfader in forum C Programming
    Replies: 9
    Last Post: 08-22-2003, 08:21 AM
  5. Help with an Array
    By omalleys in forum C Programming
    Replies: 1
    Last Post: 07-01-2002, 08:31 AM