From: tika <tikabass@yahoo.fr>
To: libstdc++@gcc.gnu.org
Subject: Questions about std::string::operator=(char)
Date: Sat, 27 Mar 2021 03:25:56 +0100 [thread overview]
Message-ID: <7eeb24bf-58cc-5316-807e-64434ecf4b83@yahoo.fr> (raw)
In-Reply-To: <7eeb24bf-58cc-5316-807e-64434ecf4b83.ref@yahoo.fr>
Synopsys:?? assigning a char to a std::string makes a string 1 char long,
but what happens if that char is zero??? And showing how easily can this
UB pass undetected through unit testing...
The story:?? I created a stupid bug, that my unit testing did not
catch....?? And ended up spending more more time debugging the test than
fixing my bug.
The bug itself is kind of boring...?? Using the return value of int
snd_get_name(int, char*) C function from the alsa library, and putting
an int into a string. That's what I think could be a rather common mistake.
Here's my piece of code, the various tests that could be applied (and
most fail to detect the bug in my code).?? It turns out that assigning a
null character to a std::string breaks a lot iof invariants we usually
depend on.?? All of gcc 10.2.1 (with libstdc++-10.2.1-9), clang 11.0.1
and icc 2021.1.2 fail to warn of the mistake with -Wall, for gcc at
least, that is both both on my system (fedora) and on godbolt.?? MSVC
does a lot better, with both warnings and different outcome, with str =
0 (correctly ?) resulting in an empty string of length zero.
I know it is UB, but I'm pretty sure the fact that this can go
undetected so easily by the most common unit testing methods makes it an
interseting one.?? Is it a feature? Is it something that is part of the
standard's private UB collection? What does the standard say about
expected invariants such as s == s.c_str() ? And about the contract of
std::basic_string::operator(Char) ?
So, here's some code that show the issue and how stcky it is... You can
also find it here: https://godbolt.org/z/cTWGWohv3
<https://godbolt.org/z/cTWGWohv3>
#include<string>
#include<cstring>
#include<iostream>
// -------------------------------------------------------------------------
// simulating what is the C driver FYI, it's the alsa sound driver,
// but that's not much relevant
char*some_text =nullptr;
voidinit_text()
{
?????? some_text =strdup("some text");
}
intget_card_name(int,char** x)
{
*x =some_text;
return0;
}
// end 'driver' code
// -------------------------------------------------------------------------
intmain()
{
?????? init_text();
?????? inti =0;
char*name;
?????? std::string s;
// my original bug... &"??! happens.
?????? s =get_card_name(i,&name);
// Should have read:
// if (!get_card_name(i, &name))
// s = name;
// simulating EXPECT_FALSE(s.empty());
?????? std::cout <<"s.empty() : "<<s.empty()<<'\n';
// simulating EXPECT_NE(s.length(), 0);
?????? std::cout <<"s.length() : "<<s.length()<<'\n';
// simulating EXPECT_NE(s, "");
?????? std::cout <<"(s == \"\") : "<<(s =="")<<'\n';
// simulating EXPECT_EQ(s, s.c_str());
?????? std::cout <<"(s == s.c_str()): "<<(s ==s.c_str())<<" <- bug
detected!\n";
// checking for transmisssion by copy
?????? std::string t =s;
?????? std::cout <<"t == s : "<<(t ==s)<<" <- transmission of odd
behaviour by copy\n";
// a trace to check contents:
?????? std::cout <<"s : \""<<s <<"\"\n";
if(!s.empty())
?????? std::cout <<"int(s.front()) : "<<(int)s.front()<<'\n';
?????? free(some_text);
returns.length();
}
next parent reply other threads:[~2021-03-27 2:26 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <7eeb24bf-58cc-5316-807e-64434ecf4b83.ref@yahoo.fr>
2021-03-27 2:25 ` tika [this message]
2021-03-27 10:35 ` Jonathan Wakely
2021-03-27 10:37 ` Jonathan Wakely
2021-03-27 14:58 ` tika
2021-03-27 15:32 ` Jonathan Wakely
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=7eeb24bf-58cc-5316-807e-64434ecf4b83@yahoo.fr \
--to=tikabass@yahoo.fr \
--cc=libstdc++@gcc.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).