Confused about "static"

M

Mike Copeland

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
 
Ö

Öö Tiib

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
 
K

K. Frank

Hello Mike (and Öö)!

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
 
M

Marcel Müller

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
 
T

Tobias Müller

Öö Tiib said:
That is same as in C. static local variables retain their value from
call to call.


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
 
M

Marcel Müller

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
 
L

Luca Risolia

Marcel said:
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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,767
Messages
2,569,570
Members
45,045
Latest member
DRCM

Latest Threads

Top