Thursday, August 20, 2020

Digest for comp.lang.c++@googlegroups.com - 25 updates in 2 topics

"daniel...@gmail.com" <danielaparker@gmail.com>: Aug 19 08:24PM -0700

> > ...
> > };
> what are you recommending he do with the code that is represented by "..." above?
 
My recommendation would be to ditch it. There are almost no good reasons
for inheriting from std::vector.
 
Daniel
Juha Nieminen <nospam@thanks.invalid>: Aug 20 05:51AM

> you're learning the wrong things. You don't need C arrays or new in
> code like this.
 
> I still think you need to unlearn a whole lot of Java.
 
I'm also sensing a rather common pattern which I see *a lot* with beginner
programmers. And that pattern is the style of programming of "let's try
random things, without even understanding what I'm doing, just to see if
it perhaps by pure chance will compile and work". A form of cargo cult
programming is also common with this pattern, ie. seeing random syntax
out there and trying to copy that syntax without understanding what it
actually means or what it's actually doing (once again just to randomly
try if it perhaps might compile and work by pure chance).
 
I have lately consulted lots of beginner programmers online, and this
kind of "let's try random things just to see if might perhaps work,
without really understanding what it actually means" can be quite
frustrating. (This is especially frustrating in an online environment
because you can't really see in real time what they are doing nor
guide them in real time about what they are doing right and wrong.)
Juha Nieminen <nospam@thanks.invalid>: Aug 20 05:54AM

> std::array<strvector, INDEX_WHAT_NUM> identifiers;
> std::array<strvector, INDEX_WHAT_NUM> random_identifiers;
> std::array<strvector, INDEX_WHAT_NUM> framework_identifiers;
 
We would first need to know if he really wants an array of vectors of
strings, or just a vector of strings. The code looks a lot like he
actually wants the latter (ie. he simply wants a vector containing
INDEX_WHAT_NUM strings). But before he confirms, any answers are just
blind guesses.
Bonita Montero <Bonita.Montero@gmail.com>: Aug 20 07:59AM +0200

A typedef isn't a wrapper.
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Aug 20 01:41AM -0700

On 8/19/2020 10:54 PM, Juha Nieminen wrote:
> actually wants the latter (ie. he simply wants a vector containing
> INDEX_WHAT_NUM strings). But before he confirms, any answers are just
> blind guesses.
 
Agreed.
RM <robert_magdziarz@wp.pl>: Aug 20 10:47AM +0200

W dniu 19.08.2020 o 13:45, RM pisze:
> a my program compiles and runs.
> Problem solved.
> Thank you very much for your answers!
 
I have one more question:
If I write:
php_result_dir = ""; // in constructor
...
TRACE("php_result_dir before:" << php_result_dir);
assert(php_result_dir.empty());
php_result_dir = argv[2]; // HERE ERROR!!!
then I have assert failed, and TRACE writes empty string after colon.
What's going on?
RM <robert_magdziarz@wp.pl>: Aug 20 11:06AM +0200

W dniu 20.08.2020 o 10:41, Chris M. Thomasson pisze:
>> INDEX_WHAT_NUM strings). But before he confirms, any answers are just
>> blind guesses.
 
> Agreed.
 
I need array of vectors. Array should be indexed by enum:
 
#define INDEX_WHAT_NUM 5
enum index_what { i_actions, i_methods, i_functions, i_properties,
i_variables }; // don't change the order
RM <robert_magdziarz@wp.pl>: Aug 20 11:20AM +0200

W dniu 19.08.2020 o 21:58, James Kuyper pisze:
 
> with
 
> vector<vector<string>> identifiers
 
> what are you recommending he do with the code that is represented by "..." above?
 
I need a datastructure with the following operations:
 
class strvector : public std::vector<std::string> {
public:
int index_of_item(const std::string &needle) const; // must be
efficient
bool has_item(const std::string &needle) const {
return index_of_item(needle) >= 0;
}
bool assign_first(const std::string &search, const std::string
&replace) {
int n = index_of_item(search);
if (n >= 0) {
(*this)[n] = replace;
return true;
}
return false;
}
std::string implode(char delim) const; // a la PHP
void append(const strvector &v) {
insert(end(), v.begin(), v.end());
}
void push_back_unique(const std::string &s) { // must be efficient
if (!has_item(s)) {
push_back(s);
}
}
// push_back(string) and operator[size_type] must be efficient
};
strvector explode(char delim, const std::string &s); // a la PHP
strvector get_filepaths(std::experimental::filesystem::path path,
std::string extension);
strvector get_subdirpaths(std::experimental::filesystem::path path);
Ian Collins <ian-news@hotmail.com>: Aug 20 09:24PM +1200

On 20/08/2020 21:06, RM wrote:
>>> blind guesses.
 
>> Agreed.
 
> I need array of vectors. Array should be indexed by enum:
 
If you know the size, use std::array.
 
 
> #define INDEX_WHAT_NUM 5
 
Don't use #define!
 
 
--
Ian.
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Aug 20 02:34AM -0700

On 8/20/2020 2:24 AM, Ian Collins wrote:
 
> If you know the size, use std::array.
 
>> #define INDEX_WHAT_NUM 5
 
> Don't use #define!
 
Self Slap! Its the C in me.
 
Christian Gollwitzer <auriocus@gmx.de>: Aug 20 11:36AM +0200

Am 20.08.20 um 11:20 schrieb RM:
> public:
>     int index_of_item(const std::string &needle) const; // must be
> efficient
 
So you want something where you could look up the strings efficiently.
How about a hashmap? std::unordered_set<std::string> ? It has a "find"
method which is O(1).
https://en.cppreference.com/w/cpp/container/unordered_set
 
I'm also not sure why you want to "replace" the keys. I would expect,
from the comment "obfuscator", that you need a way to look up the old ID
and replace it with the mangled ID. For that you could use a
std::unordered_map<std::string, std::string>
 
Christian
Jorgen Grahn <grahn+nntp@snipabacken.se>: Aug 20 10:38AM

On Thu, 2020-08-20, Juha Nieminen wrote:
> programmers. And that pattern is the style of programming of "let's try
> random things, without even understanding what I'm doing, just to see if
> it perhaps by pure chance will compile and work".
 
I've done that myself, with the Groovy language. Not my finest moment.
 
> without understanding what it actually means or what it's actually
> doing (once again just to randomly try if it perhaps might compile
> and work by pure chance).
 
Maybe. It doesn't explain all the arrays and operator new, unless he's
also consulting books from the 1990s.
 
(That's why I bother posting: if I can convince him to get a better
book/source of information, then I will have helped. It's not just a
chance to be mean.)
 
/Jorgen
 
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
James Kuyper <jameskuyper@alumni.caltech.edu>: Aug 20 08:20AM -0400

>> what are you recommending he do with the code that is represented by "..." above?
 
> My recommendation would be to ditch it. There are almost no good reasons
> for inheriting from std::vector.
 
I would tend to agree with you, but you did say "almost". Unless and
until he shows us what that code would be, I'm willing to reserve
judgement. Even if that code is in the wrong location, it probably does
something that does need to be done somewhere, so simply ditching it is
probably not the right way to fix it.
Jorgen Grahn <grahn+nntp@snipabacken.se>: Aug 20 12:25PM

On Thu, 2020-08-20, Christian Gollwitzer wrote:
> method which is O(1).
> https://en.cppreference.com/w/cpp/container/unordered_set
 
> I'm also not sure why you want to "replace" the keys.
 
And split and join (explode/implode), and a connection to file system
paths. And the class name is 'strvector', which is a description of
the implementation, rather than a name that summarizes the purpose of
the class. It's a mystery to me.
 
> from the comment "obfuscator", that you need a way to look up the old ID
> and replace it with the mangled ID. For that you could use a
> std::unordered_map<std::string, std::string>
 
From some of the code he posted (not this code) I too got the
impression that that was the goal. Also that the same obfuscator
served several separate namespaces (thus the arrays indexed by an
enum).
 
I'd do an obfuscator for a single namespace:
 
class Obfuscator {
public:
string translate(const string&);
};
 
and then use several of them in some upper-layer class.
 
Like you say, std::unordered_map would be an excellent choice for the
implementation.
 
/Jorgen
 
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
James Kuyper <jameskuyper@alumni.caltech.edu>: Aug 20 05:36AM -0700

On Thursday, August 20, 2020 at 1:59:53 AM UTC-4, Bonita Montero wrote:
> A typedef isn't a wrapper.
 
True, but how is that relevant? The keyword typedef doesn't appear
anywhere in that code. strvector is not a typedef, it's a class derived
from std::vector<std::string>.
 
It's no longer necessary to guess - RM's response to my same message
contains the details of how strvector is defined. It's far from being a
trivial wrapper for std::vector<string>. The features he's added suggest
that he'd be better off using std::unordered_set<string> rather than
strvector, but, assuming he's actually going to use those features, it's
quite clear that a simple std::vector<std::string> would not be useful
for his purposes.
RM <robert_magdziarz@wp.pl>: Aug 20 04:20PM +0200

I have one more problem. When I write:
 
class obfuscator {
...
public:
obfuscator() { // HERE PROBLEM
status = s_not_ready;
php_application_dir = "";
php_result_dir = "";
keywords = " " + reserved_keywords + " " +
strtoupper(reserved_keywords) + " ";
random_identifiers_length = default_random_identifiers_length;
extension = default_extension;
identifiers = new strvector[index_what_num];
random_identifiers = new strvector[index_what_num];
framework_identifiers = new strvector[index_what_num];
error_messages = "";
}
...
}
 
int main(int argc, const char *argv[]) {
using namespace std;
TRACE("main called" << endl);
obfuscator dirty;
 
I receive error:
 
#9 0x0000000000409f4f in std::operator+<char, std::char_traits<char>,
std::allocator<char> > (__lhs=...,
__rhs=<error reading variable: Cannot create a lazy string with
address 0x0, and a non-zero length.>) at
/usr/include/c++/7/bits/basic_string.h:5955
#10 0x0000000000408406 in obfuscator::obfuscator (this=0x7ffd5adb6070)
at src/obfuscator.hpp:79
#11 0x000000000040786b in main (argc=6, argv=0x7ffd5adb65b8)
 
The problem does not occur if I write in main():
obfuscator *dirty = new obfuscator();
RM <robert_magdziarz@wp.pl>: Aug 20 08:57PM +0200

I believe that there is problem with my constructor but I don't see my
mistake.
 
class obfuscator {
private:
enum statuses { s_not_ready, s_ready, s_checked, s_no_comments,
s_framework_remembered, s_remembered, s_generated, s_replaced, s_done }
status; // don't change the order
const std::string usage = "Usage: dirtyphp php_application_dir
php_result_dir [--reserved='space separated list of identifiers to
exclude'] [--extension=php_files_extension] [--subdirs='space separated
list of subdirectories'] [--controllers=subdirectory_of_mvc_controllers]
[--views=subdirectory_of_mvc_views] [--framework=ci
--system=path_to_framework] [--idlen=number] [--gui]";
const std::string help = std::string("") +
"...";
const size_t default_random_identifiers_length = 10;
const size_t min_random_identifiers_length = 5;
const std::string random_identifiers_suffix = "_x_x_";
const std::string default_extension = "php";
const std::string identifier = "[a-zA-Z_][a-zA-Z0-9_]+";
const std::string ci_reserved = "config db autoload active_group
query_builder smileys _doctypes foreign_characters route simpleys
platforms robots mobiles browsers lang _remap _output _utility index";
const std::string ci_subdirs = "config core controllers models
views helpers libraries";
const std::string ci_controllers = "controllers";
const std::string ci_views = "views";
const std::string yii_reserved = "";
const std::string yii_subdirs = "backend common/components
common/config common/models console/commands console/config
frontend/components frontend/config frontend/controllers frontend/lib
frontend/models frontend/views";
const std::string yii_controllers = "frontend/controllers";
const std::string yii_views = "frontend/views";
// !!! zmienić:
const std::string zf_reserved = "";
const std::string zf_subdirs = "config configs forms module modules
controllers layouts models views";
const std::string zf_controllers = "controllers";
const std::string zf_views = "views";
std::string reserved_keywords ;
std::string reserved_variables;
std::string reserved_properties;
std::string reserved_functions;
std::string reserved_methods;
enum index_what { i_actions, i_methods, i_functions, i_properties,
i_variables }; // don't change the order
constexpr unsigned short index_what_num = i_variables - i_actions + 1;
std::string php_application_dir, php_result_dir; // program parameters
std::string keywords, reserved, extension, framework,
framework_dir; // program options
strvector subdirs, controllers_dirs, views_dirs; // program options
unsigned short random_identifiers_length;
strvector *identifiers, *random_identifiers, *framework_identifiers;
std::string error_messages; // messages separated by '\n'
std::string check_not_allowed_syntax(std::string file, std::string
regexp, std::string message);
bool check_not_allowed_syntax(std::string file);
void perform_remove_comments_and_whitespaces(std::string dir);
void perform_remember_framework_identifiers(std::string dir);
void perform_remember_identifiers(std::string dir);
void perform_replace_identifiers(std::string dir);
void clear_identifiers();
// void remove_comments_and_whitespaces(std::string file_path,
std::string in_dir);
void remember_identifiers(std::string file_path, std::string
in_dir, strvector *arrids);
void generate_random_identifiers();
void replace_identifiers(std::string file_path, std::string in_dir);
 
public:
obfuscator() {
status = s_not_ready;
reserved_keywords = "and or xor __FILE__ exception __LINE__
array as break case class const continue declare default die do echo
else elseif empty enddeclare endfor endforeach endif endswitch endwhile
eval exit extends for foreach function global if include include_once
isset list new print require require_once return static switch unset use
var while __FUNCTION__ __CLASS__ __METHOD__ final php_user_filter
interface implements extends public private protected abstract clone try
catch throw cfunction old_function this";
reserved_variables = "this argc argv php_errormsg GLOBALS
_SERVER _GET _POST _COOKIE _REQUEST _ENV _FILES _SESSION HTTP_GET_VARS
HTTP_POST_VARS HTTP_COOKIE_VARS HTTP_ENV_VARS HTTP_SESSION_VARS
HTTP_SERVER_VARS";
reserved_properties = "";
reserved_functions = /* !!! PHP5 */ "__autoload __halt_compiler";
reserved_methods = /* !!! PHP5 */ "__construct __destruct
__get __set __call __callStatic __isset __unset __sleep __wakeup
__toString __invoke __set_state __clone __debugInfo";
php_application_dir = "";
php_result_dir = "";
keywords = string(" ") + reserved_keywords + string(" ") +
strtoupper(reserved_keywords) + string(" ");
random_identifiers_length = default_random_identifiers_length;
extension = default_extension;
identifiers = new strvector[index_what_num];
random_identifiers = new strvector[index_what_num];
framework_identifiers = new strvector[index_what_num];
error_messages = "";
}
~obfuscator() {
delete [] identifiers;
delete [] random_identifiers;
delete [] framework_identifiers;
}
std::string get_usage() const {
return usage;
}
std::string get_help() const {
return help;
}
std::string get_error_messages() const {
return error_messages;
}
bool check_cmdline_usage(int argc, const char *argv[]) const;
bool get_cmdline_options(int argc, const char *argv[]);
bool make_result_dir();
bool check_application(bool after_obfuscation);
bool obfuscate_application();
};
 
Program terminated with signal SIGABRT, Aborted.
#0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
51 ../sysdeps/unix/sysv/linux/raise.c: Nie ma takiego pliku ani katalogu.
(gdb) bt
#0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1 0x00007f37c5f128b1 in __GI_abort () at abort.c:79
#2 0x00007f37c6567957 in ?? () from
/usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3 0x00007f37c656dae6 in ?? () from
/usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4 0x00007f37c656db21 in std::terminate() ()
from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5 0x00007f37c656dd54 in __cxa_throw ()
from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6 0x00007f37c656e2dc in operator new(unsigned long) ()
from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#7 0x00007f37c65ffb8b in std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> >::_M_mutate(unsigned long,
unsigned long, char const*, unsigned long) () from
/usr/lib/x86_64-linux-gnu/libstdc++.so.6
#8 0x00007f37c6601133 in std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> >::_M_append(char const*,
unsigned long) ()
from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#9 0x0000000000409df5 in std::operator+<char, std::char_traits<char>,
std::allocator<char> > (__lhs=...,
__rhs=<error reading variable: Cannot create a lazy string with
address 0x0, and a non-zero length.>) at
/usr/include/c++/7/bits/basic_string.h:5955
#10 0x0000000000408382 in obfuscator::obfuscator (this=0x7ffc6babeb70)
at src/obfuscator.hpp:79
#11 0x000000000040786b in main (argc=6, argv=0x7ffc6babf0b8)
Barry Schwarz <schwarzb@delq.com>: Aug 20 11:58AM -0700

> php_result_dir = argv[2]; // HERE ERROR!!!
>then I have assert failed, and TRACE writes empty string after colon.
>What's going on?
 
Show us the type of php_result_dir.
 
--
Remove del for email
boltar@nowhere.co.uk: Aug 20 06:59PM

On Thu, 20 Aug 2020 21:24:07 +1200
 
>If you know the size, use std::array.
 
>> #define INDEX_WHAT_NUM 5
 
>Don't use #define!
 
Oh god, not this again. It should go in the moronic advice box along with
"Never use gotos!".
 
I'm guessing you've never written cross platform code or used the -D option
with gcc/clang in makefiles.
wyniijj@gmail.com: Aug 20 07:24AM -0700

For this simplifed test.cpp, all are fine. But in another roughly identical
(a little bit more members) case, g++ says:
"warning: returning reference to temporary"
"error: cannot bind non-const lvalue reference of type."
So, my question: Is such way of coding 1.legal 2.returning reference to
temporary and/or cannot bind non-const lvalue reference of type, which or
both are correct!
 
//-----------------------------------
// test.cpp
#include <iostream>
 
using namespace std;
 
class Arr {
typedef uint16_t T;
 
T arr[2];
 
public:
inline const T& lo() const { return arr[0]; };
inline T& lo() { return arr[0]; };
inline const T& hi() const { return arr[1]; };
inline T& hi() { return arr[1]; };
};
 
int main()
{
Arr a;
a.lo()=1234;
a.hi()=0;
cout << "a.lo()=" << a.lo() << ", a.hi()=" << a.hi() << endl;
return 0;
};
 
//------------------------------------
[]$ g++ test.cpp
[]$ ./a.out
a.lo()=1234, a.hi()=0
James Kuyper <jameskuyper@alumni.caltech.edu>: Aug 20 11:21AM -0400

> (a little bit more members) case, g++ says:
> "warning: returning reference to temporary"
> "error: cannot bind non-const lvalue reference of type."
 
Yes, it's quite common to have two nearly identical programs, one of
them without any problems, and the other with undefined behavior, even
though the difference between them is very small. This is a most common
when the author is unaware of the fact that the difference, while small,
is important.
That is why it was a very bad idea to post only the program that doesn't
trigger any warning and error messages.
wyniijj@gmail.com: Aug 20 09:06AM -0700

James Kuyper於 2020年8月20日星期四 UTC+8下午11時21分27秒寫道:
> is important.
> That is why it was a very bad idea to post only the program that doesn't
> trigger any warning and error messages.
[quote]
So, my question: Is such way of coding 1.legal 2.returning reference to
temporary and/or cannot bind non-const lvalue reference of type, which or
both are correct!
----
I mean the very test.cpp as shown. Even with -O2 or -Os compile option are good.
wyniijj@gmail.com: Aug 20 09:16AM -0700

wyn...@gmail.com於 2020年8月21日星期五 UTC+8上午12時06分52秒寫道:
> both are correct!
> ----
> I mean the very test.cpp as shown. Even with -O2 or -Os compile option are good.
 
It looked to me compiler can choose at will either 1.legal, accepted, or
2."warning: returning reference to temporary" and/or "error: cannot bind non-
const lvalue reference of type,..", rejected.
Bo Persson <bo@bo-persson.se>: Aug 20 07:08PM +0200


> It looked to me compiler can choose at will either 1.legal, accepted, or
> 2."warning: returning reference to temporary" and/or "error: cannot bind non-
> const lvalue reference of type,..", rejected.
 
No, the compiler doesn't make a random choice. :-)
 
However, the code sample you posted only has references to lvalues (Arr
a; is an lvalue, and so are its members). There are no temporaries involved.
 
Of course there are many cases where a conversion would occur, like when
not everything involved uses type T. But that would then be in the code
we haven't seen.
 
 
Bo Persson
James Kuyper <jameskuyper@alumni.caltech.edu>: Aug 20 01:20PM -0400

On 8/20/20 12:16 PM, wyniijj@gmail.com wrote:
...
> It looked to me compiler can choose at will either 1.legal, accepted, or
> 2."warning: returning reference to temporary" and/or "error: cannot bind non-
> const lvalue reference of type,..", rejected.
 
An implementation is permitted to complain about anything it wants to.
It can complain about the fact that you used taboo words as identifiers.
It can complain about the fact that you compiled your code on Friday the
13th.
However, a conforming implementation of C++ needs an actual legitimate
reason for refusing to translate your code. So it would help a great
deal if you could show us the code that gave the compiler you're using
justification for doing so. The code you've showed us doesn't.
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: