does std::string have something like CString::GetBuffer?

Discussion in 'C++' started by sas, May 30, 2008.

  1. sas

    sas Guest

    hi,

    i need that because the path functions for windows, like PathAppend
    and PathRemoveFileExt accept a writable zero terminated char*, but i
    didn't find that for std::string, with CString, i usually use
    GetBuffer for that

    LPTSTR CString::GetBuffer( int nMinBufLength )
     
    sas, May 30, 2008
    #1
    1. Advertising

  2. sas

    Lionel B Guest

    On Fri, 30 May 2008 03:43:45 -0700, sas wrote:

    > hi,
    >
    > i need that because the path functions for windows, like PathAppend and
    > PathRemoveFileExt accept a writable zero terminated char*, but i didn't
    > find that for std::string, with CString, i usually use GetBuffer for
    > that
    >
    > LPTSTR CString::GetBuffer( int nMinBufLength )


    const char* std::string::c_str() const

    --
    Lionel B
     
    Lionel B, May 30, 2008
    #2
    1. Advertising

  3. sas

    sas Guest

    On May 30, 2:23 pm, Lionel B <> wrote:
    > On Fri, 30 May 2008 03:43:45 -0700, sas wrote:
    > > hi,

    >
    > > i need that because the path functions for windows, like PathAppend and
    > > PathRemoveFileExt accept a writable zero terminated char*, but i didn't
    > > find that for std::string, with CString, i usually use GetBuffer for
    > > that

    >
    > > LPTSTR CString::GetBuffer( int nMinBufLength )

    >
    > const char* std::string::c_str() const
    >
    > --
    > Lionel B


    c_str doesn't work for me, because it returns a const, i want to be
    able to pass the raw zero-terminated buffer to a C function that
    changes it, then tell the string object to update with the new
    sequence.

    for example:

    int a = 5;
    CString str;
    char* buffer = str.GetBuffer(MAX_PATH);
    sprintf(buffer, "var = %d", a);
    str.ReleaseBuffer();

    str is now "var = 5"

    with string i have to do this:

    int a = 5;
    std::string str;
    char buffer[MAX_PATH];
    strcpy(buffer, str.c_str());
    sprintf(buffer, "var = %d", a);
    str = buffer;

    i have to use an additional buffer for std::string
     
    sas, May 30, 2008
    #3
  4. sas

    Lionel B Guest

    On Fri, 30 May 2008 05:41:45 -0700, sas wrote:

    > On May 30, 2:23 pm, Lionel B <> wrote:
    >> On Fri, 30 May 2008 03:43:45 -0700, sas wrote:
    >> > hi,

    >>
    >> > i need that because the path functions for windows, like PathAppend
    >> > and PathRemoveFileExt accept a writable zero terminated char*, but i
    >> > didn't find that for std::string, with CString, i usually use
    >> > GetBuffer for that

    >>
    >> > LPTSTR CString::GetBuffer( int nMinBufLength )

    >>
    >> const char* std::string::c_str() const
    >>
    >> --
    >> Lionel B

    ^^^^^^^^
    (please don't quote sigs)

    > c_str doesn't work for me, because it returns a const, i want to be able
    > to pass the raw zero-terminated buffer to a C function that changes it,
    > then tell the string object to update with the new sequence.


    No, sure. You can't "write to the c_str()" of a std::string. It's part of
    the internals of a std::string and is definitely read-only and not to be
    messed about with; hence the const.

    > for example:
    >
    > int a = 5;
    > CString str;
    > char* buffer = str.GetBuffer(MAX_PATH); sprintf(buffer, "var = %d", a);
    > str.ReleaseBuffer();
    >
    > str is now "var = 5"
    >
    > with string i have to do this:
    >
    > int a = 5;
    > std::string str;
    > char buffer[MAX_PATH];
    > strcpy(buffer, str.c_str());

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^

    This looks dangerous (does it even compile?) and is pointless anyway,
    since you later set string = buffer. Just leave it out.

    > sprintf(buffer, "var = %d", a);
    > str = buffer;
    >
    > i have to use an additional buffer for std::string


    Yes you do indeed if you want to update a std::string from a C-style
    string. In fact there's no guarantee that a std::string is even
    implemented with anything like a char buffer, zero-terminated or
    otherwise.

    --
    Lionel B
     
    Lionel B, May 30, 2008
    #4
  5. sas

    Lionel B Guest

    > On Fri, 30 May 2008 05:41:45 -0700, sas wrote:

    > * sas:
    >>
    >> with string i have to do this:
    >>
    >> int a = 5;
    >> std::string str;
    >> char buffer[MAX_PATH];
    >> strcpy(buffer, str.c_str());
    >> sprintf(buffer, "var = %d", a);
    >> str = buffer;
    >>
    >> i have to use an additional buffer for std::string


    On Fri, 30 May 2008 13:04:21 +0000, Lionel B wrote:

    > Yes you do indeed if you want to update a std::string from a C-style
    > string. In fact there's no guarantee that a std::string is even
    > implemented with anything like a char buffer, zero-terminated or
    > otherwise.


    On Fri, 30 May 2008 15:08:28 +0200, Alf P. Steinbach wrote:

    > No, you don't.
    >
    > With std::string you can use resize() to allocate a suitably large
    > buffer, and &s[0] to get a pointer to the internal buffer.


    I stand corrected. I wasn't aware that it was ever safe to write to the
    internal buffer of a std::string.

    --
    Lionel B
     
    Lionel B, May 30, 2008
    #5
  6. sas

    Kai-Uwe Bux Guest

    Lionel B wrote:

    >> On Fri, 30 May 2008 05:41:45 -0700, sas wrote:

    >
    >> * sas:
    >>>
    >>> with string i have to do this:
    >>>
    >>> int a = 5;
    >>> std::string str;
    >>> char buffer[MAX_PATH];
    >>> strcpy(buffer, str.c_str());
    >>> sprintf(buffer, "var = %d", a);
    >>> str = buffer;
    >>>
    >>> i have to use an additional buffer for std::string

    >
    > On Fri, 30 May 2008 13:04:21 +0000, Lionel B wrote:
    >
    >> Yes you do indeed if you want to update a std::string from a C-style
    >> string. In fact there's no guarantee that a std::string is even
    >> implemented with anything like a char buffer, zero-terminated or
    >> otherwise.

    >
    > On Fri, 30 May 2008 15:08:28 +0200, Alf P. Steinbach wrote:
    >
    >> No, you don't.
    >>
    >> With std::string you can use resize() to allocate a suitably large
    >> buffer, and &s[0] to get a pointer to the internal buffer.

    >
    > I stand corrected. I wasn't aware that it was ever safe to write to the
    > internal buffer of a std::string.


    It isn't yet. However, C++0X will guarantee that std::string is contiguous
    in memory. Then, it will be legal to write into the buffer. Until then, it
    will just be safe since all popular implementations of std::string already
    are contiguous. (However, last time I checked, C++0x was not slated to
    guarantee that there is a memory position for a terminating 0 char. So, you
    need to take that into account when allocating the buffer.)


    Best

    Kai-Uwe Bux
     
    Kai-Uwe Bux, May 30, 2008
    #6
  7. sas

    Guest

    On May 30, 7:23 am, Lionel B <> wrote:
    > On Fri, 30 May 2008 03:43:45 -0700, sas wrote:
    >
    > > i need that because the path functions for windows, like PathAppend and
    > > PathRemoveFileExt accept a writable zero terminated char*, but i didn't
    > > find that for std::string, with CString, i usually use GetBuffer for
    > > that

    >
    > > LPTSTR CString::GetBuffer( int nMinBufLength )

    >
    > const char* std::string::c_str() const


    I don't think this fits the OP's requirements. CString::GetBuffer(int)
    returns a *writable* buffer, and the caller can request a minimal size
    for the buffer.
     
    , May 30, 2008
    #7
  8. sas

    sas Guest

    On May 30, 4:08 pm, "Alf P. Steinbach" <> wrote:
    >          s.resize( sprintf( &s[0], "var = %d", a ) );


    nice code :)
    took me a while to figure it out

    i wanted to use std::string with PathAppend,
    here is a definition of PathAppend from msdn:



    PathAppend Function

    Appends one path to the end of another.

    Syntax

    BOOL PathAppend(
    LPTSTR pszPath,
    LPCTSTR pszMore
    );

    Parameters

    pszPath
    [in, out] A pointer to a null-terminated string to which the
    path specified in pszMore is appended. You should set the size of this
    buffer to MAX_PATH to ensure that it is large enough to hold the
    returned string.
    pszMore
    [in] A pointer to a null-terminated string of maximum length
    MAX_PATH that contains the path to be appended.

    Return Value

    Returns TRUE if successful, or FALSE otherwise.

    Remarks

    This function automatically inserts a backslash between the two
    strings, if one is not already present.

    The path supplied in pszPath cannot begin with "..\\" or ".\\" to
    produce a relative path string. If present, those periods are stripped
    from the output string. For example, appending "path3" to "..\\path1\
    \path2" results in an output of "\path1\path2\path3" rather than "..
    \path1\path2\path3".


    so this function appends one string to another, and it expects to find
    a trailing zero, unlike sprintf

    i know c_str() appends a zero (temporary), and i can use resize to set
    string to MAX_PATH, but there's no way afaik to notify it that the
    controlled sequence is updated so it should re-read it

    so there's no way to avoid that additional buffer
     
    sas, May 30, 2008
    #8
  9. sas

    Kai-Uwe Bux Guest

    Sam wrote:

    > sas writes:
    >
    >> c_str doesn't work for me, because it returns a const, i want to be
    >> able to pass the raw zero-terminated buffer to a C function that
    >> changes it, then tell the string object to update with the new
    >> sequence.

    >
    > There is no equivalent functionality in std::string. You can achieve the
    > same functionality by using the append() method to resize the string to
    > the required size, and then using std::string's iterators to mess around
    > with its contents.
    >
    > I know what you're talking about, and there is no direct equivalent in
    > std::string, and it's a good thing. MFC's sloppy class design opens many
    > opportunities for coding errors, like buffer overflows and stack smashing,
    > that leads to security holes. You will find out that using the C++ library
    > and STL containers correctly leads to good programming practices that
    > eliminates nearly all opportunities for coding errors of this nature.


    I am not so sure whether std::string is well designed in this regard. As far
    as I can see,

    str[huge_number] = 'c';

    is just as prone to buffer overflows and stack corruption as anything else.
    Now, of course, you can say that is using std::string _incorrectly_. But
    that defense can be mounted for any class that is designed with documented
    undefined behavior. By and large, safety seems not to be a major concern in
    the design of the STL and there is undefined behavior lurking around every
    corner.


    [snip]

    Best

    Kai-Uwe Bux
     
    Kai-Uwe Bux, May 31, 2008
    #9
  10. sas

    James Kanze Guest

    On May 30, 3:29 pm, "Alf P. Steinbach" <> wrote:
    > * Lionel B:
    > >> On Fri, 30 May 2008 05:41:45 -0700, sas wrote:


    > >> * sas:
    > >>> with string i have to do this:


    > >>> int a = 5;
    > >>> std::string str;
    > >>> char buffer[MAX_PATH];
    > >>> strcpy(buffer, str.c_str());
    > >>> sprintf(buffer, "var = %d", a);
    > >>> str = buffer;


    > >>> i have to use an additional buffer for std::string


    > > On Fri, 30 May 2008 13:04:21 +0000, Lionel B wrote:


    > >> Yes you do indeed if you want to update a std::string from
    > >> a C-style string. In fact there's no guarantee that a
    > >> std::string is even implemented with anything like a char
    > >> buffer, zero-terminated or otherwise.


    > > On Fri, 30 May 2008 15:08:28 +0200, Alf P. Steinbach wrote:


    > >> No, you don't.


    > >> With std::string you can use resize() to allocate a
    > >> suitably large buffer, and &s[0] to get a pointer to the
    > >> internal buffer.


    > > I stand corrected. I wasn't aware that it was ever safe to
    > > write to the internal buffer of a std::string.


    > Well it wasn't, formally, at one time.


    Officially, it still isn't, formally. The 0x version of C++ has
    not yet been formally adapted:). Practically, of course, it's
    exactly as you say.

    Note that the next version of the standard will also provide
    cleaner ways of doing this: a non-const version of data() (for
    both std::string and std::vector), rather than &s[0].

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, May 31, 2008
    #10
  11. sas

    James Kanze Guest

    On May 31, 9:40 am, Kai-Uwe Bux <> wrote:
    > Sam wrote:
    > > sas writes:


    > >> c_str doesn't work for me, because it returns a const, i
    > >> want to be able to pass the raw zero-terminated buffer to a
    > >> C function that changes it, then tell the string object to
    > >> update with the new sequence.


    > > There is no equivalent functionality in std::string. You
    > > can achieve the same functionality by using the append()
    > > method to resize the string to the required size, and then
    > > using std::string's iterators to mess around with its
    > > contents.


    > > I know what you're talking about, and there is no direct
    > > equivalent in std::string, and it's a good thing. MFC's
    > > sloppy class design opens many opportunities for coding
    > > errors, like buffer overflows and stack smashing, that leads
    > > to security holes. You will find out that using the C++
    > > library and STL containers correctly leads to good
    > > programming practices that eliminates nearly all
    > > opportunities for coding errors of this nature.


    > I am not so sure whether std::string is well designed in this
    > regard. As far as I can see,


    > str[huge_number] = 'c';


    > is just as prone to buffer overflows and stack corruption as
    > anything else.


    It's a quality of implementation issue. With the better
    implementations I use (g++, VC++), this will cause a program
    crash. With the poorer ones, it will corrupt the free space
    arena (which also leads to a program crash down the line). I've
    never seen an implementation where it would corrupt the stack,
    or where it could effectively be used to breech security,
    however.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, May 31, 2008
    #11
  12. Hi!

    Kai-Uwe Bux schrieb:
    > By and large, safety seems not to be a major concern in
    > the design of the STL and there is undefined behavior lurking around every
    > corner.


    At least the STL is not designed to work well with MFC! For my part, I'm
    happy I don't need these ugly
    please-append-my-platform-path-separator-to-my-string-if-its-not-already-there
    function or the like. I've discovered boost::path, which does that for
    me automatically.

    Frank
     
    Frank Birbacher, Jun 8, 2008
    #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. Peter Jansson
    Replies:
    5
    Views:
    6,324
    Ivan Vecerina
    Mar 17, 2005
  2. Sunner Sun
    Replies:
    23
    Views:
    9,447
    Dan Pop
    Apr 13, 2004
  3. Fei Liu
    Replies:
    9
    Views:
    448
  4. rupert
    Replies:
    8
    Views:
    548
    Jerry Coffin
    Jul 28, 2006
  5. Jeffrey Walton
    Replies:
    10
    Views:
    944
    Mathias Gaunard
    Nov 26, 2006
Loading...

Share This Page