Confused about "static"

Discussion in 'C++' started by Mike Copeland, Aug 12, 2013.

  1. The following routine seemed to work...until I used it twice in the
    same program. 2nd time through, the "static string" retained the value
    produced in the first usage call. 8<{{
    Obviously, I don't know how to use "static" to return a string value,
    but there must be way(s) to do this. Please advise. TIA

    string FileFunctions::removeExtension(string strFileName)
    {
    static string strRoot = strFileName;
    size_t pos1 = strRoot.find_last_of(".");
    if(pos1 != string::npos) strRoot.erase(pos1);
    return strRoot;
    } // removeExtension
    Mike Copeland, Aug 12, 2013
    #1
    1. Advertising

  2. Mike Copeland

    Öö Tiib Guest

    On Monday, 12 August 2013 02:53:44 UTC+3, Mike Copeland wrote:
    > The following routine seemed to work...until I used it twice in the
    > same program. 2nd time through, the "static string" retained the value
    > produced in the first usage call. 8<{{


    That is same as in C. static local variables retain their value from
    call to call.

    > Obviously, I don't know how to use "static" to return a string value,
    > but there must be way(s) to do this. Please advise. TIA
    >
    > string FileFunctions::removeExtension(string strFileName)
    > {
    > static string strRoot = strFileName;
    > size_t pos1 = strRoot.find_last_of(".");
    > if(pos1 != string::npos) strRoot.erase(pos1);
    > return strRoot;
    > } // removeExtension


    Not sure why you need static? Write something like that:

    std::string FileFunctions::removeExtension(std::string strFileName)
    {
    size_t pos1 = strFileName.find_last_of(".");
    if (pos1 != std::string::npos)
    {
    strFileName.erase(pos1);
    }
    return strFileName;
    } // removeExtension
    Öö Tiib, Aug 12, 2013
    #2
    1. Advertising

  3. Mike Copeland

    K. Frank Guest

    Hello Mike (and Öö)!

    On Sunday, August 11, 2013 7:53:44 PM UTC-4, Mike Copeland wrote:
    > The following routine seemed to work...until I used it twice in the
    > same program. 2nd time through, the "static string" retained the value
    > produced in the first usage call. 8<{{
    > Obviously, I don't know how to use "static" to return a string value,
    > but there must be way(s) to do this. Please advise. TIA
    >
    > string FileFunctions::removeExtension(string strFileName)
    > {
    > static string strRoot = strFileName;
    > size_t pos1 = strRoot.find_last_of(".");
    > if(pos1 != string::npos) strRoot.erase(pos1);
    > return strRoot;
    > } // removeExtension


    As Öö explained, there's no reason to use static here.
    His version of removeExtension is presumably what you
    want.

    However, it is worth understanding what is going on
    here.

    As Öö mentioned static variables retain their values
    in between function calls. (To avoid future confusion,
    let me say more completely "static local variables"; the
    keyword static has other meanings in other contexts.)

    Your line of code:

    static string strRoot = strFileName;

    does two things: it declares the static variable strRoot,
    and it initializes it (to the value of strFileName). But
    because it's a static variable, it only gets initialized
    once, the first time the function is run. It then remembers
    that value (as modified by chopping off the file extension)
    from call to call. (For example, try calling your function
    repeatedly with "x.y.z.u.v.w".)

    To emphasize, the "=" looks like an assignment, but is
    an initialization, and because it is an initialization
    of a static variable, it only gets executed once, the
    first time the function is called.

    However, if you replace the above line of code with the
    following two lines:

    static string strRoot;
    strRoot = strFileName;

    the first line will declare the variable (and initialize
    it to a default-constructed empty string), and the second
    line is now an assignment (not an initialization), and will
    assign strFileName to strRoot every time the function is
    called.

    With this change, your function should work as desired.
    (But, again, the use of static doesn't serve any purpose
    here.)


    Happy Hacking!


    K. Frank
    K. Frank, Aug 12, 2013
    #3
  4. On 12.08.13 05.10, K. Frank wrote:
    > static string strRoot;
    > strRoot = strFileName;


    > With this change, your function should work as desired.
    > (But, again, the use of static doesn't serve any purpose
    > here.)


    I would add that with static the function is no longer thread-safe.


    Marcel
    Marcel Müller, Aug 12, 2013
    #4
  5. Öö Tiib <> wrote:
    > On Monday, 12 August 2013 02:53:44 UTC+3, Mike Copeland wrote:
    >> The following routine seemed to work...until I used it twice in the
    >> same program. 2nd time through, the "static string" retained the value
    >> produced in the first usage call. 8<{{

    >
    > That is same as in C. static local variables retain their value from
    > call to call.
    >
    >> Obviously, I don't know how to use "static" to return a string value,
    >> but there must be way(s) to do this. Please advise. TIA
    >>
    >> string FileFunctions::removeExtension(string strFileName)
    >> {
    >> static string strRoot = strFileName;
    >> size_t pos1 = strRoot.find_last_of(".");
    >> if(pos1 != string::npos) strRoot.erase(pos1);
    >> return strRoot;
    >> } // removeExtension

    >
    > Not sure why you need static? Write something like that:
    >
    > std::string FileFunctions::removeExtension(std::string strFileName)
    > {
    > size_t pos1 = strFileName.find_last_of(".");
    > if (pos1 != std::string::npos)
    > {
    > strFileName.erase(pos1);
    > }
    > return strFileName;
    > } // removeExtension


    Just a guess:
    Probably this is a direct translation from a C function with a static local
    buffer, returning a char* to that buffer, like:

    const char* removeExtension(const char* fileName)
    {
    static char root[MAX_PATH];
    strcpy(root, fileName);
    char* pos1 = strrchr(root, '.');
    if(pos1 != NULL) pos1 = 0;
    return root;
    }

    This makes at least some sense in C, because the caller doesn't have to
    bother with deallocation of the result.

    But such an unguarded use of local static objects is really dangerous. The
    returned C string retains its value only until the next call to that
    function!
    Additionally, the function cannot be called simultaneously from different
    threads, which is even worse than just "not thread safe"!

    The same in C++ would be a returning the static local string by reference,
    which is equally dangerous.

    Tobi
    Tobias Müller, Aug 12, 2013
    #5
  6. Mike Copeland

    Luca Risolia Guest

    Marcel Müller wrote:

    > On 12.08.13 05.10, K. Frank wrote:
    >> static string strRoot;
    >> strRoot = strFileName;


    > I would add that with static the function is no longer thread-safe.


    It is in C++11.
    Luca Risolia, Aug 12, 2013
    #6
  7. On 12.08.13 10.14, Luca Risolia wrote:
    > Marcel Müller wrote:
    >
    >> On 12.08.13 05.10, K. Frank wrote:
    >>> static string strRoot;
    >>> strRoot = strFileName;

    >
    >> I would add that with static the function is no longer thread-safe.

    >
    > It is in C++11.


    No, this one not.

    The initialization of strRoot might be thread-safe, but using the same
    static string from different threads for writing (assignment) is clearly
    a race-condition with undefined behavior.


    Marcel
    Marcel Müller, Aug 12, 2013
    #7
  8. Mike Copeland

    Luca Risolia Guest

    Marcel Müller wrote:

    > On 12.08.13 10.14, Luca Risolia wrote:
    >> Marcel Müller wrote:
    >>
    >>> On 12.08.13 05.10, K. Frank wrote:
    >>>> static string strRoot;
    >>>> strRoot = strFileName;

    >>
    >>> I would add that with static the function is no longer thread-safe.

    >>
    >> It is in C++11.

    >
    > No, this one not.
    >
    > The initialization of strRoot might be thread-safe, but using the same
    > static string from different threads for writing (assignment) is clearly
    > a race-condition with undefined behavior.


    Of course, the assignment is not thread-safe, but I was commenting the "[...]
    with static [...]" part of your sentence, as merely declaring and initializing
    static local variables is thread-safe since C++11.
    Luca Risolia, Aug 12, 2013
    #8
    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. Natan

    Static vs. non-static connection

    Natan, May 24, 2004, in forum: ASP .Net
    Replies:
    8
    Views:
    7,308
    Sami Vaaraniemi
    May 26, 2004
  2. Ben
    Replies:
    3
    Views:
    412
  3. Alexander Mahr

    confused with "static"

    Alexander Mahr, Sep 24, 2003, in forum: C++
    Replies:
    29
    Views:
    840
  4. DaBrain
    Replies:
    1
    Views:
    340
    =?Utf-8?B?UGV0ZXIgQnJvbWJlcmcgW0MjIE1WUF0=?=
    Nov 15, 2006
  5. Joseph Turian
    Replies:
    9
    Views:
    346
    Bo Persson
    Sep 21, 2006
Loading...

Share This Page