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

incompatible types in assignment

543 views
Skip to first unread message

RM

unread,
Aug 14, 2020, 8:16:13 AM8/14/20
to
I am learning C++.
I have the code:

class strvector : public std::vector<std::string> {
...
};

class obfuscator {
...
strvector (*identifiers)[INDEX_WHAT_NUM],
(*random_identifiers)[INDEX_WHAT_NUM],
(*framework_identifiers)[INDEX_WHAT_NUM];
...
obfuscator() {
...
identifiers = new strvector[INDEX_WHAT_NUM];
random_identifiers = new strvector[INDEX_WHAT_NUM];
framework_identifiers = new strvector[INDEX_WHAT_NUM];
...
}
~obfuscator() {
delete [] identifiers;
delete [] random_identifiers;
delete [] framework_identifiers;
}
...
};

And I have errors:

src/obfuscator.hpp: In constructor ‘obfuscator::obfuscator()’:
src/obfuscator.hpp:75:51: error: incompatible types in assignment of
‘strvector*’ to ‘strvector [5]’
identifiers = new strvector[INDEX_WHAT_NUM];
^
src/obfuscator.hpp:76:58: error: incompatible types in assignment of
‘strvector*’ to ‘strvector [5]’
random_identifiers = new strvector[INDEX_WHAT_NUM];
^
src/obfuscator.hpp:77:61: error: incompatible types in assignment of
‘strvector*’ to ‘strvector [5]’
framework_identifiers = new strvector[INDEX_WHAT_NUM];

How to correct my code?

Sam

unread,
Aug 14, 2020, 8:43:56 AM8/14/20
to
RM writes:

> class obfuscator {
> ...
> strvector (*identifiers)[INDEX_WHAT_NUM], (*random_identifiers)
> [INDEX_WHAT_NUM], (*framework_identifiers)[INDEX_WHAT_NUM];

identifiers is an array. It pops into existence all of its own. Ditto for
the others.

> ...
> obfuscator() {
> ...
> identifiers = new strvector[INDEX_WHAT_NUM];
> random_identifiers = new strvector[INDEX_WHAT_NUM];
> framework_identifiers = new strvector[INDEX_WHAT_NUM];

These class members already exist. They don't need to be `new`ed or deleted.

Now, you do need to `new` each one of these INDEX_WHAT_NUM strvectors,
individually, one by one.

> ...
> }
> ~obfuscator() {
> delete [] identifiers;
> delete [] random_identifiers;
> delete [] framework_identifiers;
> }

And then delete each one, one by one in the destructor.

But really, let me let you in on a very closely held secret. Promise not to
tell anyone, this secret that's known only by a handful of C++ gurus in the
world:

In modern C++, there is rarely a need to new or delete anything. Rather, you
use containers do all that work for you. Or, in case of fixed-size arrays,
just declare them:

strvector identifiers[INDEX_WHAT_NUM], random_identifiers[INDEX_WHAT_NUM],
framework_identifiers[INDEX_WHAT_NUM];


Its unclear whether strvector has a default constructor or not. Just
declaring a plain array requires a default constructor. Otherwise, simply
use std::vector, with a smart use of `reserve()` to avoid needless copying,
and let std::vector do all the work of new-ing and delete-ing, all by itself.

Its, of course, important to understand how dynamic memory allocations work.
But it is rarely needed in most simple use cases.

> How to correct my code?

Get rid of new and delete, complete. Use vectors, or lists, or some other
container that will do this for you.

Bonita Montero

unread,
Aug 14, 2020, 8:57:31 AM8/14/20
to
Although there might be workarounds the issue of the OP is still
interesting.

RM

unread,
Aug 14, 2020, 9:03:52 AM8/14/20
to
W dniu 14.08.2020 o 14:43, Sam pisze:
>> How to correct my code?
>
> Get rid of new and delete, complete. Use vectors, or lists, or some
> other container that will do this for you.
>
I tried heap allocation because I had core dumped when I used stack
allocation (local variables). I don't know why because I use little memeory.

RM

unread,
Aug 14, 2020, 9:46:12 AM8/14/20
to
> I tried heap allocation because I had core dumped when I used stack
> allocation (local variables). I don't know why because I use little
> memeory.

I use g++ in Linux Mint.

RM

unread,
Aug 14, 2020, 9:55:25 AM8/14/20
to
W dniu 14.08.2020 o 15:46, RM pisze:
To be precise I have core dumped and I have in gdb:

#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 0x00007f98bd7d5801 in __GI_abort () at abort.c:79
#2 0x00007f98bde2a957 in ?? () from
/usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3 0x00007f98bde30ae6 in ?? () from
/usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4 0x00007f98bde30b21 in std::terminate() ()
from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5 0x00007f98bde30d54 in __cxa_throw ()
from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6 0x00007f98bde312dc in operator new(unsigned long) ()
from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#7 0x00007f98bdec2b8b 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 0x00007f98bdec4133 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 0x00000000004098d1 in std::operator+<char, std::char_traits<char>,
std::allocator<char> > (__lhs=..., __rhs="")
at /usr/include/c++/7/bits/basic_string.h:5955
#10 0x000000000040838e in obfuscator::obfuscator (this=0x7ffd4feca0e0)
at src/obfuscator.hpp:69
#11 0x000000000040781b in main (argc=6, argv=0x7ffd4feca678)
at src/dirtyphp.cpp:37

RM

unread,
Aug 14, 2020, 10:16:40 AM8/14/20
to
W dniu 14.08.2020 o 15:55, RM pisze:
After reinstalling g++ I have:

#0 __memmove_avx_unaligned_erms ()
at ../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:371
371 ../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S: Nie ma
takiego pliku ani katalogu.
(gdb) bt
#0 __memmove_avx_unaligned_erms ()
at ../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:371
#1 0x00007fa7a3e55bda 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
#2 0x00007fa7a3e57133 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
#3 0x00000000004098d1 in std::operator+<char, std::char_traits<char>,
std::allocator<char> > (__lhs=...,

__rhs="\020(\v\244\247\177\000\000\002\000\000\000\000\000\000\000H\374\n\244\247\177\000\000\002\000\000\000\000\000\000\000\000t\v\244\247\177\000\000\000\000\000\000\000\000\000\000\330\373\n\244\247\177\000\000\002\000\000\000\000\000\000\000`)\261\243\247\177",
'\000' <repeats 26 times>,
"\020\330\n\244\247\177\000\000\002\000\000\000\000\000\000\000`)\261\243\247\177\000\000\001\000\001\002\003\004\005\006\a\b\t\n\v\f\r\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037
!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMN"...)
at /usr/include/c++/7/bits/basic_string.h:5955
#4 0x000000000040838e in obfuscator::obfuscator (this=0x7ffe10828cb0)
at src/obfuscator.hpp:69
#5 0x000000000040781b in main (argc=6, argv=0x7ffe10829248)
at src/dirtyphp.cpp:37

Barry Schwarz

unread,
Aug 14, 2020, 10:47:30 AM8/14/20
to
On Fri, 14 Aug 2020 14:16:01 +0200, RM <robert_m...@wp.pl> wrote:

>I am learning C++.
>I have the code:
>
>class strvector : public std::vector<std::string> {
>...
>};
>
>class obfuscator {
>...
> strvector (*identifiers)[INDEX_WHAT_NUM],
>...
> obfuscator() {
> ...
> identifiers = new strvector[INDEX_WHAT_NUM];
> ...
> }
>...
>};
>
>And I have errors:
>
>src/obfuscator.hpp: In constructor ‘obfuscator::obfuscator()’:
>src/obfuscator.hpp:75:51: error: incompatible types in assignment of
>‘strvector*’ to ‘strvector [5]’
> identifiers = new strvector[INDEX_WHAT_NUM];

This error message is inconsistent with the above code. identifiers
does not have type strvector[5]. It has type strvector(*)[5] which is
completely different.

The easiest way for us to help you would be for you to provide a
small, complete, compilable program that produces the error in
question. When you post the program in a message, use cut and paste
rather than retype it. Retyping often introduces mistakes that don't
appear in the original.

In a subsequent message you stated you had problems using arrays that
were declared explicitly. Show us that code also so we can see what
you are doing wrong.

Based on both messages, I think you have a fundamental
misunderstanding about arrays but we will probably be able to correct
that also when you show us the code.

--
Remove del for email

Bo Persson

unread,
Aug 14, 2020, 12:32:19 PM8/14/20
to
You have to consider if you want an array of pointers,

strvector (*identifiers)[INDEX_WHAT_NUM]

or a pointer to an array

new strvector[INDEX_WHAT_NUM]

Those are not the same thing.


BTW, a std::vector doesn't store the data elements on the stack, but
uses heap allocation internally (and likely does that correctly :-)). If
you run out of stack space, you have some other problem.

Alf P. Steinbach

unread,
Aug 14, 2020, 1:06:30 PM8/14/20
to
On 14.08.2020 14:16, RM wrote:
> [snip]
>     strvector (*identifiers)[INDEX_WHAT_NUM],

This is a pointer to a complete array of `strvector`, because

`*identifiers` gives you what identifiers points to, and
THAT[n] gives you the beyond-the-last item.

Instead of using the old C syntax you could write

std::array<strvector, INDEX_WHAT_NUM>* identifiers;

Or instead of using the standard library type you could define

template< class T > using Type_ = T;

and then write

Type_<strvector[INDEX_WHAT_NUM]>* identifiers;

The question is whether that's what you really wanted, because


> [snip]
>         identifiers = new strvector[INDEX_WHAT_NUM];

... produces a `strvector*, i.e. a pointer to the first item in the
allocated array, and not a pointer to the complete array as such.

The difference is just one of type, not of memory address.

But it's enough to make the compiler say no.


[snip]
> How to correct my code?

It depends what you want.

If you just want a dynamic size array of strings, then

vector<string> m_identifiers;

But if you want a dynamic size array of dynamic size arrays of strings, then

vector<vector<string>> m_identifiers;

That's closest to the presented code but I believe you really want the
first one.


- Alf

Juha Nieminen

unread,
Aug 14, 2020, 1:26:22 PM8/14/20
to
RM <robert_m...@wp.pl> wrote:
> strvector (*identifiers)[INDEX_WHAT_NUM],
> (*random_identifiers)[INDEX_WHAT_NUM],
> (*framework_identifiers)[INDEX_WHAT_NUM];

The answers to this question go to show that even many experienced C++
programmers don't know their pointer syntax.

Type (*name)[size]

is a pointer to a Type[size], ie. an array of size elements of type Type.

This is *not* the same thing as a pointer-to-Type. This is a
pointer-to-Type[size], which is different.

For instance, if you increment a Type*, it will advance by sizeof(Type) bytes,
but if you increment a Type(*)[size], it will advance by sizeof(Type)*size
bytes.

Most often Type(*name)[size] is used as a pointer to a 2-dimensional array,
where the second dimension is 'size'. In other words:

Type table[12][34];
Type (*ptr)[34] = table;

Here you see that if you do a ++ptr, it will advance to the next row in
the array, ie. it will advance by an entire row, ie by sizeof(Type)*34
bytes.

Your code does not look like you want a pointer to a 2-dimensional array.
It looks to me that you simply wanted:

strvector *identifiers, *random_identifiers, *framework_identifiers;

These are pointers-to-strvector, which also double as "pointer to an array
of strvector objects" (an ambiguity inherited from C).

That being said, it's usually recommended against using raw pointers and
'new'. Just use members of strvector directly:

strvector identifiers, random_identifiers, framework_identifiers;

Since strvector is just an std::vector, there's really no reason not to.

Barry Schwarz

unread,
Aug 14, 2020, 2:17:09 PM8/14/20
to
On Fri, 14 Aug 2020 18:32:02 +0200, Bo Persson <b...@bo-persson.se>
wrote:

>You have to consider if you want an array of pointers,
>
>strvector (*identifiers)[INDEX_WHAT_NUM]

That is not an array of pointers. It is a pointer to an (entire)
array. An array of pointers would be declared as
strvector *array[5]

Sam

unread,
Aug 14, 2020, 5:51:35 PM8/14/20
to
RM writes:

>> Get rid of new and delete, complete. Use vectors, or lists, or some other
>> container that will do this for you.
>>
> I tried heap allocation because I had core dumped when I used stack
> allocation (local variables). I don't know why because I use little memeory.

If you do not understand the reason why your program crashes, trying
different things at random will rarely fix anything. Especially other things
that you don't even fully understand the inner workings of.

You need to investigate the reason for your crashes, and fix them.

Unfortunately, posting your backtraces to the Intertubes does not convey
anything meaningful. Backtraces are utterly useless to anyone except the one
who produced the backtrace. Backtraces aren't, by themselves a "here's where
the bug is" solution. All that a backtrace tells you is the sequence of
function calls that led to the crash. How does that tell you what the bug
is? Very rarely it does, but almost never.

Backtraces are only a starting point. Unfortunately there is no paint-by-
numbers, cookie-cutter recipe for figuring out the bug, from a backtrace.
Each crash is unique, and distinct in its nature. Typically one would see,
from the backtrace, where your written code ends, and system libraries start
(if any), then go up to call stack back to where your code made the library
call, then investigate the state of the program and the data, at the time of
the library call. Inspect all variables, pointers, determine what the
problem with the state of the program is. Maybe even back up a few more
stack frames, if it's clear that something went sideways further up the call
chain. Or, you may discover such a dumpster fire already in progress that
the only thing that you can do is set a breakpoint earlier in the code, at
some meaningful place, before execution reaches here, run the program again,
and see how things shape up at an earlier point in the execution.

Jorgen Grahn

unread,
Aug 15, 2020, 5:10:55 PM8/15/20
to
On Fri, 2020-08-14, RM wrote:
> I am learning C++.
> I have the code:
>
> class strvector : public std::vector<std::string> {
> ...
> };
>
> class obfuscator {
> ...
> strvector (*identifiers)[INDEX_WHAT_NUM],
> (*random_identifiers)[INDEX_WHAT_NUM],
> (*framework_identifiers)[INDEX_WHAT_NUM];
> ...
> obfuscator() {
> ...
> identifiers = new strvector[INDEX_WHAT_NUM];
> random_identifiers = new strvector[INDEX_WHAT_NUM];
> framework_identifiers = new strvector[INDEX_WHAT_NUM];
> ...
> }
> ~obfuscator() {
> delete [] identifiers;
> delete [] random_identifiers;
> delete [] framework_identifiers;
> }
> ...
> };

What sources are you learning from, and what's your programming
background?

I don't know what problem your code should solve, but most solutions
don't involve C arrays, new/delete, or inheriting from std::vector.
Some of this indicates an influence from Java. If you know Java, you
need to forget it while programming in C++.

If you want to map identifiers to obfuscated identifiers, I recommend
an implementation based on std::unordered_map.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

RM

unread,
Aug 19, 2020, 7:45:16 AM8/19/20
to
W dniu 14.08.2020 o 14:16, RM pisze:
> How to correct my code?

I changed my code to the following:
strvector *identifiers, *random_identifiers, *framework_identifiers;
a my program compiles and runs.
Problem solved.
Thank you very much for your answers!

Juha Nieminen

unread,
Aug 19, 2020, 9:02:49 AM8/19/20
to
Can you show us your constructor and destructor? Because I have a hunch that
you might not be doing it correctly.

RM

unread,
Aug 19, 2020, 9:29:54 AM8/19/20
to
W dniu 19.08.2020 o 15:02, Juha Nieminen pisze:
obfuscator() {
static_assert(i_variables == INDEX_WHAT_NUM - 1);
status = s_not_ready;
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 = "";

Bonita Montero

unread,
Aug 19, 2020, 9:38:51 AM8/19/20
to
Am 14.08.2020 um 14:16 schrieb RM:
> I am learning C++.
> I have the code:
> class strvector : public std::vector<std::string> {
> ...
> };
> class obfuscator {
> ...
>     strvector (*identifiers)[INDEX_WHAT_NUM],
> (*random_identifiers)[INDEX_WHAT_NUM],
> (*framework_identifiers)[INDEX_WHAT_NUM];
> ...
>     obfuscator() {
>     ...
>         identifiers = new strvector[INDEX_WHAT_NUM];
>         random_identifiers = new strvector[INDEX_WHAT_NUM];
>         framework_identifiers = new strvector[INDEX_WHAT_NUM];
>         ...
>     }
>     ~obfuscator() {
>         delete [] identifiers;
>         delete [] random_identifiers;
>         delete [] framework_identifiers;
>     }
> ...
> };

Why do you use an array of pointers to std::vector<string> ?
Use a vector<vector<string>>, and if you have performance-concerns
use .reserve().

Juha Nieminen

unread,
Aug 19, 2020, 11:09:00 AM8/19/20
to
RM <robert_m...@wp.pl> wrote:
> identifiers = new strvector[INDEX_WHAT_NUM];

You are not creating a vector of strings there. You are creating
an array of INDEX_WHAT_NUM vectors, each one containing strings.

Somehow I doubt that's what you intended. It looks to me more
like you want *one* vector containing INDEX_WHAT_NUM strings,
rather than an array of INDEX_WHAT_NUM vectors, each containing
strings.

You should not be playing with new and delete if you don't know
what you are doing. If what you want is just a vector of strings,
you do this:

//----------------------------------------------------
class MyClass
{
strvector identifiers;

public:
MyClass()
{
identifiers.resize(INDEX_WHAT_NUM);
}
};
//----------------------------------------------------

If what you really want is a vector of vectors of strings,
then you do this:

//----------------------------------------------------
class MyClass
{
std::vector<strvector> identifiers;

public:
MyClass()
{
identifiers.resize(INDEX_WHAT_NUM);
}
};
//----------------------------------------------------

You don't need a destructor in either case.

In the first case above you have *one* vector containing
many strings inside it.

In the second case above you have a vector containing
one or more strvector objects, each containing many strings
inside them.

In neither case is 'new' and 'delete' needed nor recommended.

Barry Schwarz

unread,
Aug 19, 2020, 12:55:45 PM8/19/20
to
identifiers and the other variables declared above are not arrays of
pointers. Each is a pointer to an array. That is why each use of new
produced a diagnostic.

Bonita Montero

unread,
Aug 19, 2020, 1:15:55 PM8/19/20
to
Ok, it's a pointer to an array of objects and not a pointer-array.
But this isn't RAII-safe. If one allocation fails after another
the allocation before isn't cleaned up. Instead you could use a#
vector of objects.

James Kuyper

unread,
Aug 19, 2020, 1:33:39 PM8/19/20
to
On Wednesday, August 19, 2020 at 9:38:51 AM UTC-4, Bonita Montero wrote:
> Am 14.08.2020 um 14:16 schrieb RM:
> > I am learning C++.
> > I have the code:
> > class strvector : public std::vector<std::string> {
> > ...
> > };
> > class obfuscator {
> > ...
> >     strvector (*identifiers)[INDEX_WHAT_NUM],
...
> Why do you use an array of pointers to std::vector<string> ?

strvector is not a typedef for std::vector<string>, it is a class derived from std::vector<string>.

An array of pointers to strvector would be declared as follows:

strvector *identifiers[INDEX_WHAT_NUM];

What he actually wrote was

strvector (*identifiers)[INDEX_WHAT_NUM];

which declares a pointer to an array of strvectors of length INDEX_WHAT_NUM.

Bonita Montero

unread,
Aug 19, 2020, 1:47:46 PM8/19/20
to
> strvector is not a typedef for std::vector<string>, it is a class derived from std::vector<string>.
> An array of pointers to strvector would be declared as follows:
> strvector *identifiers[INDEX_WHAT_NUM];
> What he actually wrote was
> strvector (*identifiers)[INDEX_WHAT_NUM];
> which declares a pointer to an array of strvectors of length INDEX_WHAT_NUM.

Your posting is superfluous since I already corrected that.
But my tip to use a vector<vector<string>> is nevertheless correct.

James Kuyper

unread,
Aug 19, 2020, 2:32:02 PM8/19/20
to
I don't think so. First of all, strvector is derived from
std::vector<string>. He might not have had any good reason for doing so,
but unless you know more about what he's doing than he's publicly
explained, it could very well be that he needs for strvector to be a
non-trivial wrapper for std::vector<string>.

More importantly, his latest messages indicate that he's changed over to

strvector *identifier;

His judgment that this is the correct fix to his problem is suspect, but
if his code actually compiles with that declaration, I think it's
unlikely to be the case that what he actually needs is
std::vector<strvector>.

Bonita Montero

unread,
Aug 19, 2020, 2:50:10 PM8/19/20
to
Don't talk around to be somehow right. He wasn't using a wrapper.
What I suggested was a better replacement for his code.

Jorgen Grahn

unread,
Aug 19, 2020, 3:15:12 PM8/19/20
to
You wrote in your first posting that you're learning C++ ... but
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.

James Kuyper

unread,
Aug 19, 2020, 3:58:46 PM8/19/20
to
On Wednesday, August 19, 2020 at 2:50:10 PM UTC-4, Bonita Montero wrote:
> Don't talk around to be somehow right. He wasn't using a wrapper.

On Friday, August 14, 2020 at 8:16:13 AM UTC-4, RM wrote:
...
> class strvector : public std::vector<std::string> {
> ...
> };

If you don't call that a wrapper, what do you call it?
More directly to the point, regardless of what term you use for it, if he followed your suggestion of replacing

strvector (*identifiers)[INDEX_WHAT_NUM]

with

vector<vector<string>> identifiers

what are you recommending he do with the code that is represented by "..." above?

Chris M. Thomasson

unread,
Aug 19, 2020, 4:09:00 PM8/19/20
to
On 8/14/2020 5:16 AM, RM wrote:
> I am learning C++.
> I have the code:
>
> class strvector : public std::vector<std::string> {
> ...
> };
>
> class obfuscator {
> ...
>     strvector (*identifiers)[INDEX_WHAT_NUM],
> (*random_identifiers)[INDEX_WHAT_NUM],
> (*framework_identifiers)[INDEX_WHAT_NUM];
[...]
> How to correct my code?


Would something like this work for you?
____________________________________________
#include <iostream>
#include <array>
#include <vector>


#define INDEX_WHAT_NUM 3


struct strvector : public std::vector<strvector>
{
strvector()
{
std::cout << this << "::strvector::strvector()\n";
}

~strvector()
{
std::cout << this << "::strvector::~strvector()\n";
}
};


struct obfuscator
{
std::array<strvector, INDEX_WHAT_NUM> identifiers;
std::array<strvector, INDEX_WHAT_NUM> random_identifiers;
std::array<strvector, INDEX_WHAT_NUM> framework_identifiers;
};


int main()
{
{
obfuscator ob;
}

return 0;
}
____________________________________________


?

daniel...@gmail.com

unread,
Aug 19, 2020, 11:25:03 PM8/19/20
to
On Wednesday, August 19, 2020 at 3:58:46 PM UTC-4, james...@alumni.caltech.edu wrote:
> On Wednesday, August 19, 2020 at 2:50:10 PM UTC-4, Bonita Montero wrote:
> > Don't talk around to be somehow right. He wasn't using a wrapper.
> On Friday, August 14, 2020 at 8:16:13 AM UTC-4, RM wrote:
> ...
> > class strvector : public std::vector<std::string> {
> > ...
> > };
> 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

unread,
Aug 20, 2020, 1:51:31 AM8/20/20
to
Jorgen Grahn <grahn...@snipabacken.se> wrote:
> You wrote in your first posting that you're learning C++ ... but
> 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

unread,
Aug 20, 2020, 1:54:46 AM8/20/20
to
Chris M. Thomasson <chris.m.t...@gmail.com> wrote:
> 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

unread,
Aug 20, 2020, 1:59:53 AM8/20/20
to
A typedef isn't a wrapper.

Chris M. Thomasson

unread,
Aug 20, 2020, 4:42:09 AM8/20/20
to
Agreed.

RM

unread,
Aug 20, 2020, 4:47:54 AM8/20/20
to
W dniu 19.08.2020 o 13:45, RM pisze:
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

unread,
Aug 20, 2020, 5:06:44 AM8/20/20
to
W dniu 20.08.2020 o 10:41, Chris M. Thomasson pisze:
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

unread,
Aug 20, 2020, 5:20:18 AM8/20/20
to
W dniu 19.08.2020 o 21:58, James Kuyper pisze:
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

unread,
Aug 20, 2020, 5:24:19 AM8/20/20
to
On 20/08/2020 21:06, RM wrote:
> W dniu 20.08.2020 o 10:41, Chris M. Thomasson pisze:
>> On 8/19/2020 10:54 PM, Juha Nieminen wrote:
>>> Chris M. Thomasson <chris.m.t...@gmail.com> wrote:
>>>>    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.
>>>
>>
>> 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!

> enum index_what { i_actions, i_methods, i_functions, i_properties,
> i_variables }; // don't change the order
>

--
Ian.

Chris M. Thomasson

unread,
Aug 20, 2020, 5:34:25 AM8/20/20
to
On 8/20/2020 2:24 AM, Ian Collins wrote:
> On 20/08/2020 21:06, RM wrote:
>> W dniu 20.08.2020 o 10:41, Chris M. Thomasson pisze:
>>> On 8/19/2020 10:54 PM, Juha Nieminen wrote:
>>>> Chris M. Thomasson <chris.m.t...@gmail.com> wrote:
>>>>>     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.
>>>>
>>>
>>> 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!

Self Slap! Its the C in me.

Christian Gollwitzer

unread,
Aug 20, 2020, 5:36:27 AM8/20/20
to
Am 20.08.20 um 11:20 schrieb RM:
> W dniu 19.08.2020 o 21:58, James Kuyper pisze:
> 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

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

unread,
Aug 20, 2020, 6:38:58 AM8/20/20
to
On Thu, 2020-08-20, Juha Nieminen wrote:
> Jorgen Grahn <grahn...@snipabacken.se> wrote:
>> You wrote in your first posting that you're learning C++ ... but
>> 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".

I've done that myself, with the Groovy language. Not my finest moment.

> 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).

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.)

James Kuyper

unread,
Aug 20, 2020, 8:20:56 AM8/20/20
to
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

unread,
Aug 20, 2020, 8:25:26 AM8/20/20
to
On Thu, 2020-08-20, Christian Gollwitzer wrote:
> Am 20.08.20 um 11:20 schrieb RM:
>> W dniu 19.08.2020 o 21:58, James Kuyper pisze:
>> 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
>
> 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.

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.

> 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>

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.

James Kuyper

unread,
Aug 20, 2020, 8:36:20 AM8/20/20
to
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

unread,
Aug 20, 2020, 10:21:00 AM8/20/20
to
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

unread,
Aug 20, 2020, 2:57:35 PM8/20/20
to
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

unread,
Aug 20, 2020, 2:58:33 PM8/20/20
to
Show us the type of php_result_dir.

--
Remove del for email

bol...@nowhere.co.uk

unread,
Aug 20, 2020, 2:59:33 PM8/20/20
to
On Thu, 20 Aug 2020 21:24:07 +1200
Ian Collins <ian-...@hotmail.com> wrote:
>On 20/08/2020 21:06, RM wrote:
>> W dniu 20.08.2020 o 10:41, Chris M. Thomasson pisze:
>>> On 8/19/2020 10:54 PM, Juha Nieminen wrote:
>>>> Chris M. Thomasson <chris.m.t...@gmail.com> wrote:
>>>>>    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.
>>>>
>>>
>>> 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!

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.

Bo Persson

unread,
Aug 20, 2020, 3:09:48 PM8/20/20
to
Apparently the bad call comes from here:

#10 0x0000000000408382 in obfuscator::obfuscator (this=0x7ffc6babeb70)
at src/obfuscator.hpp:79

So which line is number 79?



Bo Persson


Mike Terry

unread,
Aug 20, 2020, 5:13:02 PM8/20/20
to
I'm wondering what's going on with the strtoupper(). Bad return value
(reference to defunct stack frame object or something) perhaps? Anyway,
OP would do well to learn to use a debugger to step through the failing
constructor, examining variables at the failure point...

Mike.

Chris M. Thomasson

unread,
Aug 20, 2020, 5:26:31 PM8/20/20
to
Agreed. A nice debugger and the OP's careful eye should help.

RM

unread,
Aug 21, 2020, 2:06:52 AM8/21/20
to
W dniu 20.08.2020 o 21:09, Bo Persson pisze:
Line 79:
obfuscator() {

Bo Persson

unread,
Aug 21, 2020, 3:15:49 AM8/21/20
to
Ok, so the problem manifests itself in the constructor. The next hint
from the runtime is that it happens in a call to operator+. The only
place I can see is this line:

keywords = string(" ") + reserved_keywords + string(" ") +
strtoupper(reserved_keywords) + string(" ");

I wouldn't expect the well tested standard library parts to have a bug
that creates a std::string containing a null pointer, so the suspect is
likely to be the non-standard strtoupper.


Bo Persson




David Brown

unread,
Aug 21, 2020, 3:48:29 AM8/21/20
to
Ian was a bit short here. The common advice is "don't use #define when
there are better ways to get the effect you want". (The same applies to
"goto", obviously.) And there are better ways to do it in this case, as
there usually are in C++.

> I'm guessing you've never written cross platform code or used the -D
> option with gcc/clang in makefiles.
>

Knowing a little of Ian's work, you are guessing incorrectly.
Pre-processor conditional compilation is a good reason for using
#define'd constants rather than "const", "constexpr" or "enum". So is C
compatibility, if that's important (it sometimes is in headers).

As an aside, it would be /so/ nice in C++ to have a way to access the
first and last (numerically) elements in an enumeration. Other
languages have it, like Ada's 'First and 'Last attributes, and Pascal's
"low" and "high" functions.

RM

unread,
Aug 21, 2020, 4:05:27 AM8/21/20
to
In debugger I saw random values of private const members (in
constructor). I changed const to constexpr.
Now I see different errors at sequent runs:

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 0x00007fd34482f8b1 in __GI_abort () at abort.c:79
#2 0x00007fd344e84957 in ?? () from
/usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3 0x00007fd344e8aae6 in ?? () from
/usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4 0x00007fd344e8ab21 in std::terminate() ()
from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5 0x00007fd344e8ad54 in __cxa_throw ()
from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6 0x00007fd344e8b2dc in operator new(unsigned long) ()
from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#7 0x00007fd344f1cb8b 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 0x00007fd344f1e133 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: Cannot access memory at address 0x800000007f>)
at /usr/include/c++/7/bits/basic_string.h:5955
#10 0x0000000000408382 in obfuscator::obfuscator (this=0x7ffceddf9690)
at src/obfuscator.hpp:79
#11 0x000000000040786b in main (argc=6, argv=0x7ffceddf9bd8)
---Type <return> to continue, or q <return> to quit---
at src/dirtyphp.cpp:37


or:


#0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1 0x00007fd46f5778b1 in __GI_abort () at abort.c:79
#2 0x00007fd46fbcc957 in ?? () from
/usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3 0x00007fd46fbd2ae6 in ?? () from
/usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4 0x00007fd46fbd2b21 in std::terminate() ()
from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5 0x00007fd46fbd2d54 in __cxa_throw ()
from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6 0x00007fd46fbd32dc in operator new(unsigned long) ()
from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#7 0x00007fd46fc64b8b 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 0x00007fd46fc66133 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=0x7fffba1ac430)
at src/obfuscator.hpp:79
#11 0x000000000040786b in main (argc=6, argv=0x7fffba1ac978)

RM

unread,
Aug 21, 2020, 4:27:44 AM8/21/20
to

>> I'm wondering what's going on with the strtoupper().  Bad return value
>> (reference to defunct stack frame object or something) perhaps?
>> Anyway, OP would do well to learn to use a debugger to step through
>> the failing constructor, examining variables at the failure point...
>
> Agreed. A nice debugger and the OP's careful eye should help.
>
string strtoupper(string s) {
// convert string to back to upper case
for_each(s.begin(), s.end(), [](char &c) {
c = ::toupper(c);
});
return s;
}

RM

unread,
Aug 21, 2020, 4:55:50 AM8/21/20
to
Sometimes program goes much farther (constructor finishes) and I see:

Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x00007f5d376a0df0 in std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> >::~basic_string() ()
from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
(gdb) bt
#0 0x00007f5d376a0df0 in std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> >::~basic_string() ()
from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#1 0x000000000040a46f in std::_Destroy<std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> > > (__pointer=0x71)
at /usr/include/c++/7/bits/stl_construct.h:98
#2 0x000000000040a39f in
std::_Destroy_aux<false>::__destroy<std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> >*> (__first=0x71,
__last=0x4) at /usr/include/c++/7/bits/stl_construct.h:108
#3 0x000000000040a1d2 in std::_Destroy<std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> >*> (__first=0x71, __last=0x4)
at /usr/include/c++/7/bits/stl_construct.h:137
#4 0x000000000040a0c1 in std::_Destroy<std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> >*,
std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char> > > (__first=0x71, __last=0x4)
at /usr/include/c++/7/bits/stl_construct.h:206
#5 0x00000000004108a8 in std::vector<std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> >,
std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char> > > >::_M_erase_at_end (
this=0x8bdae8, __pos=0x71) at /usr/include/c++/7/bits/stl_vector.h:1518
#6 0x0000000000410816 in std::vector<std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> >,
std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char> > > >::clear (

RM

unread,
Aug 21, 2020, 5:11:52 AM8/21/20
to
Why I have different errors at sequent runs. Program is always run with
same arguments. May there's some problem with compilation?
Here is my Makefile:

#ifeq ($(ARCH),win32)
## Windows with the VC++ compiler
#ObjSuf = obj
#SrcSuf = cxx
#ExeSuf = .exe
#DllSuf = dll
#OutPutOpt = -out:
#CXX = cl
#CXXOPT = -O2
#CXXOPT = -Z7
#CXXFLAGS = $(CXXOPT) -G5 -GR -GX -MD -DWIN32 -D_WINDOWS -nologo \
# -DVISUAL_CPLUSPLUS -D_X86_=1 -D_DLL
#LD = link
#LDOPT = -opt:ref
#LDOPT = -debug
#LDFLAGS = $(LDOPT) -pdb:none -nologo
#SOFLAGS = -DLL

CXX := -c++ # gcc czy g++?
CXXFLAGS := -Wall -Wextra -Werror -no-pie # -pedantic-errors; add
"-no-pie" to the CMAKE_CXX_FLAGS
LDFLAGS := -L/usr/lib -lstdc++ -lstdc++fs -lm # -Lsrc/boost_1_65_0/lib/
-lboost_regex-gcc34-mt-d-1_3
BUILD := ./build
OBJ_DIR := $(BUILD)/objects
APP_DIR := $(BUILD)/apps
TARGET := dirtyphp
INCLUDE := -Iinclude/ # -I src/boost_1_65_0
SRC := $(wildcard src/*.cpp)

OBJECTS := $(SRC:%.cpp=$(OBJ_DIR)/%.o)

all: build $(APP_DIR)/$(TARGET)

$(OBJ_DIR)/%.o: %.cpp
@mkdir -p $(@D)
$(CXX) $(CXXFLAGS) $(INCLUDE) -c $< -o $@ $(LDFLAGS)

$(APP_DIR)/$(TARGET): $(OBJECTS)
@mkdir -p $(@D)
$(CXX) $(CXXFLAGS) -o $(APP_DIR)/$(TARGET) $^ $(LDFLAGS)

.PHONY: all build clean debug release

build:
@mkdir -p $(APP_DIR)
@mkdir -p $(OBJ_DIR)

debug: CXXFLAGS += -DDEBUG -g
debug: all

test: CXXFLAGS += -pg # dodałem dynamic execution profiler
test: all

release: CXXFLAGS += -O2
release: all # production

clean:
-@rm -rvf $(OBJ_DIR)/*
-@rm -rvf $(APP_DIR)/*

RM

unread,
Aug 21, 2020, 5:25:38 AM8/21/20
to
I forgot to tell you one very imortant thing.
Program was running well. Suddenly it started generating core, alghough
I entered no changes to the source code.
Reinstalling compiler doesn't help.

Juha Nieminen

unread,
Aug 21, 2020, 6:34:11 AM8/21/20
to
RM <robert_m...@wp.pl> wrote:
> identifiers = new strvector[index_what_num];
> random_identifiers = new strvector[index_what_num];
> framework_identifiers = new strvector[index_what_num];

If you are just going to ignore all the advice given to you, why are you
even asking here?

Your approach at asking here seems to be "how do I get this to compile?"
instead of "how should I implement this properly?"

Just because it might compile doesn't mean it's correct. And even if it
appears to work correctly, that doesn't mean it's error-free or implemented
in a proper and advisable way.

(For starters, you aren't following the "rule of three" which means your
class will misbehave in certain circumstances. If you followed the
advice given to you of avoiding raw pointers and 'new' and 'delete', that
wouldn't be a problem and you wouldn't need to worry about it. Your code
would also become much simpler and safer.)

Juha Nieminen

unread,
Aug 21, 2020, 6:36:00 AM8/21/20
to
You are not following the advise given to you. You have serious memory
management issues in your code, so it's no wonder it's randomly crashing.

Don't use 'new' and 'delete'. Follow the advise given to you.

RM

unread,
Aug 21, 2020, 8:08:09 AM8/21/20
to
W dniu 21.08.2020 o 12:33, Juha Nieminen pisze:
Sorry.
I repaired my code.
Now it works perfectly!
Problem solved.
Thank you for your answers.

Alf P. Steinbach

unread,
Aug 21, 2020, 8:53:52 AM8/21/20
to
On 21.08.2020 09:48, David Brown wrote:
> [snip]
> As an aside, it would be /so/ nice in C++ to have a way to access the
> first and last (numerically) elements in an enumeration. Other
> languages have it, like Ada's 'First and 'Last attributes, and Pascal's
> "low" and "high" functions.

struct Weekdays{ enum Enum: int{
monday, tuesday, wednesday, thursday, friday, saturday, sunday, _
} };

template< class Enum_wrapper >
auto n_values() -> int { return Enum_wrapper::_; }

Yes?

- Alf

Juha Nieminen

unread,
Aug 21, 2020, 10:28:19 AM8/21/20
to
RM <robert_m...@wp.pl> wrote:
> I repaired my code.
> Now it works perfectly!

Pardon me if I remain a bit skeptical, but anyway.

Jorgen Grahn

unread,
Aug 21, 2020, 11:07:30 AM8/21/20
to
Surely he meant one you wouldn't have to define yourself; it would
always be there, with the same name and syntax.

RM

unread,
Aug 21, 2020, 11:24:16 AM8/21/20
to
W dniu 21.08.2020 o 16:28, Juha Nieminen pisze:
I tested my PHP obfuscator with two CodeIgniter
projects and it works.

Juha Nieminen

unread,
Aug 21, 2020, 12:11:38 PM8/21/20
to
Alf P. Steinbach <alf.p.stein...@gmail.com> wrote:
> struct Weekdays{ enum Enum: int{
> monday, tuesday, wednesday, thursday, friday, saturday, sunday, _
> } };
>
> template< class Enum_wrapper >
> auto n_values() -> int { return Enum_wrapper::_; }
>
> Yes?

If you are making a switch block for that enumerated type, many
compilers, given your normal warning flags, will warn if not all
the enumerated names have a case (and there is no default branch).
That can be slightly annoying in the case of that "amount" name
there.

Another issue is that now that "amount" entry becomes a valid
value for anything that takes a parameter of that enumerated type.
Sometimes that's perfectly ok and can in fact be useful. Othertimes
it can be a nuisance because it's not a valid value and you need
to add a check for it.

Alf P. Steinbach

unread,
Aug 21, 2020, 12:20:37 PM8/21/20
to
On 21.08.2020 18:11, Juha Nieminen wrote:
> Alf P. Steinbach <alf.p.stein...@gmail.com> wrote:
>> struct Weekdays{ enum Enum: int{
>> monday, tuesday, wednesday, thursday, friday, saturday, sunday, _
>> } };
>>
>> template< class Enum_wrapper >
>> auto n_values() -> int { return Enum_wrapper::_; }
>>
>> Yes?
>
> If you are making a switch block for that enumerated type, many
> compilers, given your normal warning flags, will warn if not all
> the enumerated names have a case (and there is no default branch).
> That can be slightly annoying in the case of that "amount" name
> there.

Yes.

I wonder if there is some C++17 or C++20 attribute that can help tell
the compiler to shut up?

I have a kind of feeling that I've seen that, but I can't remember.


> Another issue is that now that "amount" entry becomes a valid
> value for anything that takes a parameter of that enumerated type.
> Sometimes that's perfectly ok and can in fact be useful. Othertimes
> it can be a nuisance because it's not a valid value and you need
> to add a check for it.

No. If you need to check for `_` then you need to check for any possible
value, including unnamed ones. Presence or not of `_` does not matter
for that, but `_` can help the checking.

- Alf

David Brown

unread,
Aug 21, 2020, 2:00:38 PM8/21/20
to
No.

This is just an alternative (though perhaps a convenient one at times)
to the more traditional:

enum days {
Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday,
noOfDays
};

It suffers from the same problem - "noOfDays" is a valid enumeration
constant for "days" - syntactically it is a "day", but is not logically
a day.

Amongst the other disadvantages is that it spoils the very useful
-Wswitch and -Wswitch-enum warnings in gcc (and, I think, clang) that
check that switches on enum types are complete.




David Brown

unread,
Aug 21, 2020, 2:01:20 PM8/21/20
to
Yes, that's what I would like.

Keith Thompson

unread,
Aug 21, 2020, 2:42:06 PM8/21/20
to
enum days {
Monday, firstday=Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday, lastday=Sunday
};

--
Keith Thompson (The_Other_Keith) Keith.S.T...@gmail.com
Working, but not speaking, for Philips Healthcare
void Void(void) { Void(); } /* The recursive call of the void */

Alf P. Steinbach

unread,
Aug 21, 2020, 6:40:32 PM8/21/20
to
On 21.08.2020 20:00, David Brown wrote:
> On 21/08/2020 14:53, Alf P. Steinbach wrote:
>> On 21.08.2020 09:48, David Brown wrote:
>>>  [snip]
>>> As an aside, it would be /so/ nice in C++ to have a way to access the
>>> first and last (numerically) elements in an enumeration.  Other
>>> languages have it, like Ada's 'First and 'Last attributes, and Pascal's
>>> "low" and "high" functions.
>>
>> struct Weekdays{ enum Enum: int{
>>     monday, tuesday, wednesday, thursday, friday, saturday, sunday, _
>> } };
>>
>> template< class Enum_wrapper >
>> auto n_values() -> int { return Enum_wrapper::_; }
>>
>> Yes?
>>
>
> No.
>
> This is just an alternative (though perhaps a convenient one at times)
> to the more traditional:
>
> enum days {
> Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday,
> noOfDays
> };
>
> It suffers from the same problem - "noOfDays" is a valid enumeration
> constant for "days" - syntactically it is a "day", but is not logically
> a day.

That's a problem with using an ordinary name directly as an enumerator.

That's why I used `_` as enumerator name, and `n_values` as name used
elsewhere.


> Amongst the other disadvantages

Only one has been mentioned, and that's for your own rewrite.


> is that it spoils the very useful
> -Wswitch and -Wswitch-enum warnings in gcc (and, I think, clang) that
> check that switches on enum types are complete.

No, it doesn't.


#include <iostream>
using std::cout, std::endl;

#include <iterator>
using std::size;

template< class Enum_wrapper >
constexpr int n_enum_values = Enum_wrapper::_;

using C_str = const char*;

[[noreturn]] void ub() { throw; }

struct Weekdays{ enum Enum: int{
monday, tuesday, wednesday, thursday, friday, saturday, sunday, _
}; };

void operator++( Weekdays::Enum& value )
{
value = static_cast<Weekdays::Enum>( value + 1 );
}

auto to_english_via_switch_on( const Weekdays::Enum day )
-> C_str
{
switch( day ) {
case Weekdays::monday: return "Monday";
case Weekdays::tuesday: return "Tuesday";
case Weekdays::wednesday: return "Wednesday";
case Weekdays::thursday: return "Thursday";
case Weekdays::friday: return "Friday";
case Weekdays::saturday: return "Saturday";
#ifndef WARN
case Weekdays::sunday: return "Sunday";
#endif
case Weekdays::_: ub();
}
ub();
}

auto to_english_via_indexing( const Weekdays::Enum day )
-> C_str
{
constexpr C_str names[] =
{
"Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
"Saturday", "Sunday"
};
static_assert( size( names ) == n_enum_values<Weekdays> );

return names[day];
}

auto main()
-> int
{
#ifdef SWITCH
const auto& to_english = to_english_via_switch_on;
#else
const auto& to_english = to_english_via_indexing;
#endif

for( Weekdays::Enum value = {}; value < n_enum_values<Weekdays>;
++value ) {
if( value ) {
cout << ", ";
}
cout << to_english( value );
}
cout << endl;
}


Hth.,

- Alf

David Brown

unread,
Aug 21, 2020, 8:45:57 PM8/21/20
to
That might help in some cases. But again, "firstday" and "lastday" are
not part of the logical list of days. When I have a "real" enum (as
distinct from just using enum as a convenient way of making some
constants), I want it to contain only the elements that are logically
part of that group.

So I'd rather write:

enum days {
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday,
};
constexpr days firstday = Monday;
constexpr days lastday = Sunday;

That works for me here. It's one more thing you can get wrong if you
add more to the enum type later (unlikely for days, but plausible for
other enums).

And it would be /vastly/ nicer if I could just write:

constexpr days firstday = first(days);
constexpr days lastday = last(days);

or some similar general syntax.



0 new messages