Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

std::string s3 = s3; ?!?

104 views
Skip to first unread message

Ralf Fassel

unread,
Jan 18, 2019, 9:16:07 AM1/18/19
to
This compiles w/o warnings or errors in g++ version 4.8.5 (Opensuse
42.3) and g++ 7.3.1 (Opensuse 15):

#include <string>
std::string func(std::string s) {
return s;
}
int main(int argc, char **argv) {
std::string s1 = func(s1);
std::string s2(s2);
std::string s3 = s3;
return 0;
}

(and of course crashes at runtime...)

I would *at least* have expected some compiler diagnostics similar to e.g.
int i = i;
t.cc:7:11: warning: ‘i’ is used uninitialized in this function [-Wuninitialized]

and in fact I would have expected an error along the lines "s1/s2/s3 is
used before init".

MSVC 2017 raises an error about s2 not being known, but if I comment
that line out, it also compiles (and crashes)...

R'

Alf P. Steinbach

unread,
Jan 18, 2019, 12:36:03 PM1/18/19
to
The probability of doing something wrong when an identifier is used in
the declaration of that identifier, is IMO /very/ high.

One can construct artificial examples where one might argue that it's a
useful language feature, e.g. for a circular list with header node,

Node header{ &header };

But.

Anyway it's there. Compilers have to accept it. But as you point out,
they really should diagnose it.

With the above node example I get no diagnostic from `g++ foo.cpp
-std=c++17 --pedantic -Wall` with MinGW g++ 8.2.0, and no diagnostic
from `cl /std:c++17 /W4 foo.cpp` with MSVC 2017. :( If however I remove
the `&`, then both warn about using `header` uninitialized.


Cheers!,

- Alf



Mr Flibble

unread,
Jan 18, 2019, 12:39:26 PM1/18/19
to
Taking the address of an unconstructed object isn't the same as taking the
value of an unconstructed object.

/Flibble

--
“You won’t burn in hell. But be nice anyway.” – Ricky Gervais

“I see Atheists are fighting and killing each other again, over who
doesn’t believe in any God the most. Oh, no..wait.. that never happens.” –
Ricky Gervais

"Suppose it's all true, and you walk up to the pearly gates, and are
confronted by God," Bryne asked on his show The Meaning of Life. "What
will Stephen Fry say to him, her, or it?"
"I'd say, bone cancer in children? What's that about?" Fry replied.
"How dare you? How dare you create a world to which there is such misery
that is not our fault. It's not right, it's utterly, utterly evil."
"Why should I respect a capricious, mean-minded, stupid God who creates a
world that is so full of injustice and pain. That's what I would say."

Alf P. Steinbach

unread,
Jan 18, 2019, 12:53:10 PM1/18/19
to
Right, but (the language feature:) it requires the name to be available
for use before the end of the declaration.


Cheers!,

- Alf

Alf P. Steinbach

unread,
Jan 18, 2019, 1:28:43 PM1/18/19
to
On 18.01.2019 19:18, Stefan Ram wrote:
> Ralf Fassel <ral...@gmx.de> writes:
>> std::string s1 = func(s1);
>> std::string s2(s2);
>> std::string s3 = s3;
>
> warning: variable 's1' is uninitialized when used within its own initialization [clang-diagnostic-uninitialized]
> warning: variable 's2' is uninitialized when used within its own initialization [clang-diagnostic-uninitialized]
> warning: variable 's3' is uninitialized when used within its own initialization [clang-diagnostic-uninitialized]
>
> gcc.gnu.org/bugzilla/show_bug.cgi?id=71228

Interesting.

But `-Winit-self`, as mentioned somewhat sarcastically in a response to
that bug report, doesn't work (apparently no effect) with MinGW g++ 8.2.0.

Cheers!

- Alf

Manfred

unread,
Jan 18, 2019, 1:50:44 PM1/18/19
to
I think there has been some development in gcc after that bug report.

#include <iostream>

int main()
{
int n { n };

std::cout << n << std::endl;
}

[tmp]$ g++ -Wall uninit.cc && ./a.out
uninit.cc: In function ‘int main()’:
uninit.cc:7:7: warning: ‘n’ is used uninitialized in this function
[-Wuninitialized]
int n { n };
^
0
[tmp]$

===

But.

#include <iostream>
#include <string>

int main()
{
std::string s { s };

std::cout << s;
}

[tmp]$ c++ -Wall selfref.cc && ./a.out
[tmp]$

>
> Cheers!
>
> - Alf
>

Öö Tiib

unread,
Jan 21, 2019, 5:34:46 AM1/21/19
to
On Friday, 18 January 2019 16:16:07 UTC+2, Ralf Fassel wrote:
> This compiles w/o warnings or errors in g++ version 4.8.5 (Opensuse
> 42.3) and g++ 7.3.1 (Opensuse 15):
>
> #include <string>
> std::string func(std::string s) {
> return s;
> }
> int main(int argc, char **argv) {
> std::string s1 = func(s1);
> std::string s2(s2);
> std::string s3 = s3;
> return 0;
> }
>
> (and of course crashes at runtime...)

Formally the code is well formed, but reading objects before
construction is undefined behavior like reading objects
after destruction is undefined behavior. We may take
and pass references and pointers to such objects but not
to read.

Undefined behavior that always crashes is among best kind
of undefined behavior there is. What you complain?

>
> I would *at least* have expected some compiler diagnostics similar to e.g.
> int i = i;
> t.cc:7:11: warning: ‘i’ is used uninitialized in this function [-Wuninitialized]

Actually I get something like that from clang on your code:

warning: variable 's1' is uninitialized when used within its own initialization [-Wuninitialized]

Compilers have become very helpful these days.

> and in fact I would have expected an error along the lines "s1/s2/s3 is
> used before init".
>
> MSVC 2017 raises an error about s2 not being known, but if I comment
> that line out, it also compiles (and crashes)...

The C++ compiler vendors have put lot of effort into diagnosing
if the code is nonsensical. However in any useful language the
amount of different ways to express nonsense is endless. And
C++ is especially prone to that since language standard is
literally full of cases marked as "undefined behavior" (nonsense
that is not required to be diagnosed).
0 new messages