Thursday, March 24, 2016

Digest for comp.lang.c++@googlegroups.com - 18 updates in 8 topics

Robbie Hatley <see.my.sig@for.my.address>: Mar 24 10:21AM -0700

I wrote a couple of functions in C++ to print out human-readable
local time and date strings (should be PDT in AM/PM format if
executed in my area) if given current time in time_t format from
time() in the <ctime> header. To test the functions I put them
in a test program (see below).
 
But the program failed to run, even though it compiled without warning,
with a whole mess of warnings turned on:
 
%make time-test.exe DEBUG=1 PEDANTIC=1
Using pattern rule %.exe:%.cpp to compile time-test.cpp to time-test.exe:
g++ -I /rhe/include -pedantic -Wall -Wextra -Wfloat-equal -Wshadow -Wcast-qual -Wcast-align -Wconversion -Winline
-Wcomments -Wundef -Wunused-macros -Wold-style-cast -Woverloaded-virtual -std=gnu++14 time-test.cpp -L/rhe/lib -L/lib
-lrh -lfl -ly -lm -lname -o /rhe/bin/test/time-test.exe
time-test.exe is up to date.
 
(No errors. No warnings.)
 
But at runtime, it fails abysmally. It gets to a certain point
and just quits, not even executing the rest of the program.
I expected it to write date and time strings, but the
execution crashed catastrophically about halfway through the
source code, without printing any error messages.
 
After hours of struggle, I *did* determine the problem:
I'd inadvertently initialized a std::string variable to 0,
instead of to "". But why did that even compile???
Why did g++ not scream about "illegal initialization of
a std::string object to an integer value" or some such???
 
The program that reproduces the bug begins as follows;
notice the line marked "OH, MY!!!":
 
#include <iostream>
#include <iomanip>
#include <string>
#include <ctime>
 
// Get local date from time_t time:
std::string GetDate
(
time_t Seconds1970, // seconds since 00:00:00UTC on Jan 1, 1970
int Length // date format: 0=micro, 1=short, 2=long
)
{
struct tm * TimeFields = NULL;
std::string DayOfWeek = "";
std::string Month = 0; // OH, MY!!!
int DayOfMonth = 0;
int Year = 0;
TimeFields = localtime(&Seconds1970);
Year = TimeFields->tm_year + 1900;
DayOfMonth = TimeFields->tm_mday;
...etc...
...etc...
...etc...
 
 
--
Cheers,
Robbie Hatley
Midway City, CA, USA
perl -le 'print "\154o\156e\167o\154f\100w\145ll\56c\157m"'
http://www.well.com/user/lonewolf/
https://www.facebook.com/robbie.hatley
scott@slp53.sl.home (Scott Lurndal): Mar 24 06:54PM

>executed in my area) if given current time in time_t format from
>time() in the <ctime> header. To test the functions I put them
>in a test program (see below).
 
Frankly, I'd just use 'strftime'.
 
char buf[MAXTIMESTRINGSIZE];
struct tm *tm = ::localtime(&Seconds1970);
size_t diag = ::strftime(buf, sizeof(buf), "%Y/%m/%d %h:%M %p %Z", tm);
if (diag != 0) {
return std::string(buf);
} else {
throw "Buffer overflow";
}
 
2016/03/24 11:52 AM PDT
 
http://pubs.opengroup.org/onlinepubs/9699919799/functions/strftime.html
Robbie Hatley <see.my.sig@for.my.address>: Mar 24 03:04PM -0700

On 3/24/2016 11:02 AM, Stefan Ram wrote:
 
 
> . One might now be able to say that »0« does not point to
> an array, in which case the execution of the initialization
> would have UB (17.6.4.11).
 
Ah, so that (sort of) explains why it even compiled. However,
while a compiler can't tell what the value of the input to a
parameterized constructor is going to be at runtime, in this
case the input is written as a literal, in which case it's known
at compile time. So unless the the author of a C++ compiler thinks
that 0 (aka the NULL pointer) can somehow point to a valid
C string, I don't see why the author wouldn't make the compiler
flag the following as being an error:
 
std::string s = 0; // This pointer points NOWHERE.
s = "banana"; // Let's crash the system!!! WHEEE!!!
 
> This in independent of what »g++« allows, since this is
> »comp.lang.c++«, not »comp.lang.g++«.
 
I don't see how what g++ allows (or what *any* C++ compiler allows)
can be independent of what C++ itself allows, if the authors of
such compilers wish to say "our c++ compiler is compliant with the
C++ standard". So, in my opinion, the authors of g++ screwed up
by not bothering to check for an extremely obvious error.
 
But on the other hand, the product costs $0.00 and comes with no
warranty:
 
%g++ --version
g++ (GCC) 5.3.0
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
So perhaps I should dive into the source code, come up with a fix for this
bug, and send to to FSF?
 
 
--
Cheers,
Robbie Hatley
Midway City, CA, USA
perl -le 'print "\154o\156e\167o\154f\100w\145ll\56c\157m"'
http://www.well.com/user/lonewolf/
https://www.facebook.com/robbie.hatley
Robbie Hatley <see.my.sig@for.my.address>: Mar 24 03:31PM -0700

On 3/24/2016 11:54 AM, Scott Lurndal wrote:
 
> throw "Buffer overflow";
> }
 
> 2016/03/24 11:52 AM PDT
 
Firstly, my primary reason for posting here was to see why
g++ would allow a std::string to be initalized to 0. Hence the
title of my post.
 
As for your code, while I will look into strftime() to refresh
my knowledge of how it works, that's not the approach I took
for my time & date functions. I was more interested in getting
*away* from fixed-size manually-allocated arrays of char*,
and going to std::string as much as possible, especially since
these functions return std::string and will be in my personal
library and used by various C++ programs I write.
 
My implementation looks more like THIS:
 
====== BEGIN File /rhe/src/test/time-test.cpp ==================
 
#include <iostream>
#include <sstream>
#include <iomanip>
#include <string>
#include <ctime>
 
using std::cin;
using std::cout;
using std::cerr;
using std::endl;
using std::setfill;
using std::setw;
 
// Get local date from time_t time:
std::string GetDate
(
time_t Seconds1970, // seconds since 00:00:00UTC on Jan 1, 1970
int Format // date format: 0=micro, 1=short, 2=long
)
{
struct tm * TP = NULL;
std::ostringstream OS = std::ostringstream ();
 
TP = localtime(&Seconds1970);
if (NULL == TP)
{
cerr << "ERROR in GetDate(): localtime returned NULL pointer." << endl;
exit(666);
}
 
if (0 == Format) // if user wants micro date format
{
OS << TP->tm_year + 1900 << "-"
<< setw(2) << setfill('0') << TP->tm_mon + 1 << "-"
<< setw(2) << setfill('0') << TP->tm_mday;
}
else if (1 == Format) // if user wants short date format
{
const char * ShortDays[7] =
{"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
const char * ShortMonths[12] =
{"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
OS << ShortDays[TP->tm_wday] << " "
<< ShortMonths[TP->tm_mon] << " "
<< setw(2) << setfill('0') << TP->tm_mday << ", "
<< TP->tm_year + 1900;
}
else // For any other value of Format, return full-length date:
{
const char * LongMonths[12] =
{"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"};
const char * LongDays[7] =
{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
OS << LongDays[TP->tm_wday] << " "
<< LongMonths[TP->tm_mon] << " "
<< setw(2) << setfill('0') << TP->tm_mday << ", "
<< TP->tm_year + 1900;
}
return OS.str();
}
 
// Get local time from time_t time:
std::string GetTime
(
time_t Seconds1970, // seconds since 00:00:00UTC on Jan 1, 1970
int Format // time format: 0=leading zero, 1=NO leading zero
)
{
struct tm * TP = NULL;
int Hour = 0;
std::string Meridien = std::string ();
std::ostringstream OS = std::ostringstream ();
 
TP = localtime(&Seconds1970);
if (NULL == TP)
{
cerr << "ERROR in GetTime(): localtime returned NULL pointer." << endl;
exit(666);
}
 
Hour = (TP->tm_hour + 11) % 12 + 1;
Meridien = (TP->tm_hour < 12) ? "AM" : "PM";
OS << setw(2) << setfill(0==Format ? '0' : ' ') << Hour << ":"
<< setw(2) << setfill('0') << TP->tm_min << ":"
<< setw(2) << setfill('0') << TP->tm_sec << Meridien;
return OS.str();
}
 
int main (void)
{
int i = 0;
time_t Time = 0;
std::string MicroDate = "";
std::string ShortDate = "";
std::string LongDate = "";
std::string TimeString = "";
 
Time = std::time(NULL);
for ( i = 0 ; i < 50 ; ++i )
{
MicroDate = GetDate(Time, 0);
ShortDate = GetDate(Time, 1);
LongDate = GetDate(Time, 2);
TimeString = GetTime(Time, 0);
cout << "MicroDate = " << MicroDate << endl;
cout << "ShortDate = " << ShortDate << endl;
cout << "LongDate = " << LongDate << endl;
cout << "TimeString = " << TimeString << endl;
Time += 3600;
cout << endl;
}
return 0;
}
 
====== END File /rhe/src/test/time-test.cpp ==================
 
 
--
Cheers,
Robbie Hatley
Midway City, CA, USA
perl -le 'print "\154o\156e\167o\154f\100w\145ll\56c\157m"'
http://www.well.com/user/lonewolf/
https://www.facebook.com/robbie.hatley
Ian Collins <ian-news@hotmail.com>: Mar 25 12:08PM +1300

On 03/25/16 11:31, Robbie Hatley wrote:
> and going to std::string as much as possible, especially since
> these functions return std::string and will be in my personal
> library and used by various C++ programs I write.
 
This is one case where fixed-size arrays *are* the best fit!
 
--
Ian Collins
Vir Campestris <vir.campestris@invalid.invalid>: Mar 24 11:03PM

On 23/03/2016 19:28, Ian Collins wrote:
> Second try using an alternative compiler. The two I use make the cause
> much clearer:
 
The trouble is that while Clang (and, in competition, GCC) have spent a
lot of time and trouble making sensible error messages, and Microsoft
have not, I am not yet aware of an IDE for them which is any where near
as good as the Microsoft one.
 
That may be an issue for his students.
 
Andy
ram@zedat.fu-berlin.de (Stefan Ram): Mar 24 06:02PM

>std::string Month = 0;
 
I am not sure what is happening here. But it seems that 0 is
used to initialize a string object via the constructor that
accepts a char *.
 
This would use
 
string( char const * s );
 
which requires 21.4.2p7, i.e.,
 
Requires: s points to an array
 
. One might now be able to say that »0« does not point to
an array, in which case the execution of the initialization
would have UB (17.6.4.11). This in independent of what »g++«
allows, since this is »comp.lang.c++«, not »comp.lang.g++«.
ram@zedat.fu-berlin.de (Stefan Ram): Mar 24 06:44PM

>an array, in which case the execution of the initialization
>would have UB (17.6.4.11). This in independent of what »g++«
>allows, since this is »comp.lang.c++«, not »comp.lang.g++«.
 
g++ cannot know the run-time values of expressions.
 
For example, in
 
::std::string s = f();
 
g++ cannot know whether f() returns 0. This might be one
reason for the lack of a diagnostics.
 
Another reason might be that in general it is perfectly
valid to call a char-*-constructor with 0. It is only in
the case of this special constructor that 0 is forbidden.
 
So the compiler would need to include special code to check
the English language preconditions of known functions in the
special case that the compiler knows the values of the arguments.
 
A more general solution would be an extension of the language
with a new keyword »nonzero«:
 
string( char const * nonzero s );
 
. See also
 
gcc.gnu.org/ml/gcc-patches/2015-05/msg00824.html
 
.
Stuart Redmann <DerTopper@web.de>: Mar 24 04:03PM +0100

Stefan Ram wrote:
[snip]
> to /call/ such functions, not to /write/ them. What do I
> need to teach about references in this case, so that errors
> in the client's code are avoided?)
 
 
Since this is an educational problem it may be worth mentioning that some
programming languages that aim to be a successor of C have been designed in
such a way that the user has to use a different syntax for passing by
reference. For example in C# you have to use the keyword "ref" in the
parameter list.
 
Regards,
Stuart
Jerry Stuckle <jstucklex@attglobal.net>: Mar 23 11:47PM -0400

On 3/23/2016 3:08 PM, Gareth Owen wrote:
> asshole. And "humble" is absolutely not one of the words they use.
 
> "If you killed Ted Cruz on the floor of the Senate, and the trial was in
> the Senate, nobody would convict you." -- Lindsey Graham
 
Very true. Here in the D.C. area, he has a terrible reputation amongst
those who know him.
 
--
==================
Remove the "x" from my email address
Jerry Stuckle
jstucklex@attglobal.net
==================
Jerry Stuckle <jstucklex@attglobal.net>: Mar 23 11:48PM -0400


> To his credit, Lindsey Graham has changed his mind and started
> fund raising for Ted Cruz. There's an article about that on
> www.dailywire.com .
 
Only because Lindsey doesn't want Trump to win. Lindsey is part of the
"old guard" who will lose a lot of power if Trump wins. It is purely
selfish on his part.
 
--
==================
Remove the "x" from my email address
Jerry Stuckle
jstucklex@attglobal.net
==================
scott@slp53.sl.home (Scott Lurndal): Mar 24 12:58PM

>>> pray for Brussels and Paris.
 
>> Praying achieves absolutely nothing
 
>Not true. It makes the pray-er feel better about themselves.
 
Which is fundamentally selfish. Pun intended.
Christof Warlich <christof.warlich1@gmail.com>: Mar 23 11:33PM -0700

Am Mittwoch, 23. März 2016 21:44:53 UTC+1 schrieb Öö Tiib:
> What is the benefit of using 'std::bind'? I felt it as sort of obsolete
> with lambdas available.
 
You are right, using a lambda with capture by reference instead of std::bind solves my (initial) problem :-). Many thanks for your suggestion!
woodbrian77@gmail.com: Mar 23 04:40PM -0700

> If Java supporters insist on a long, boring description,
> they should be willing to let shorter and sweeter descriptions
> be placed before them.
 
Java has 16 lines of description on this page:
 
https://en.wikipedia.org/wiki/Serialization
 
. C++ has 4 lines of description. Would others
like to see the Java description reduced to 5 or 6
lines? Another idea is to arrange the languages
either chronologically or alphabetically. I think
either of those would be an improvement.
 
Brian
Ebenezer Enterprises - In G-d we trust.
http://webEbenezer.net
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Mar 24 12:24AM

> lines? Another idea is to arrange the languages
> either chronologically or alphabetically. I think
> either of those would be an improvement.
 
If you think you can improve the article then do so: others will either
agree with your edits or they won't just don't be tempted to write
another fucking advert for your software.
 
/Flibble
woodbrian77@gmail.com: Mar 23 07:35PM -0700

On Wednesday, March 23, 2016 at 7:24:46 PM UTC-5, Mr Flibble wrote:

> If you think you can improve the article then do so: others will either
> agree with your edits or they won't
 
I put the Java description after the C++ description.
 
Please don't swear here.
 
Brian
Ebenezer Enterprises - "Do not be bound together with unbelievers;
for what partnership have righteousness and lawlessness, or what
fellowship has light with darkness?" 2nd Corinthians 6:14
 
http://webEbenezer.net
woodbrian77@gmail.com: Mar 23 03:26PM -0700

On Wednesday, March 23, 2016 at 8:35:29 AM UTC-5, Scott Lurndal wrote:
> woodbrian77@gmail.com writes:
 
> >The national motto of the United states is
 
> "Out of many, one" (act of congress, 1782).
 
I believe that was the original motto. As Alf notes,
"In G-d we trust" goes back to 1956. It was on the money
long before that, though. Dennis Prager talks about the
"American Trinity" as being "Out of many, one", "In G-d we
trust," and liberty.
 
https://duckduckgo.com/?q=american+trinity+dennis+prager&t=h&ia=videos&iai=epXJ1SAa5ck
 
 
Brian
Ebenezer Enterprises
http://webEbenezer.net
"Öö Tiib" <ootiib@hot.ee>: Mar 23 06:13PM -0700


> Walls are important for privacy and private property. I'm
> a posterboy for walls in terms of closed source. Without
> that wall, I'd be left to the whims of "leaders" like Obama.
 
Poster boy of privacy, property and walls? Issues with camel and eye of
needle pop into mind. Search engines suggest Matthew 19:24
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com.

No comments: