[Bug c++/102577] Function frame size in relation to variables in conditional subscopes

2021-10-08 Thread krzyk240 at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102577

Krzysztof Małysa  changed:

   What|Removed |Added

 Status|RESOLVED|UNCONFIRMED
 Resolution|INVALID |---

--- Comment #3 from Krzysztof Małysa  ---
I have received no explanation, maybe nobody saw my comment... I don't know
what to do to receive explanation so let's try changing the status.

[Bug c++/102577] Function frame size in relation to variables in conditional subscopes

2021-10-03 Thread krzyk240 at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102577

--- Comment #2 from Krzysztof Małysa  ---
Could you explain why this is correct? For example, quoting a relevant part of
the C++ standard will do. As I said, I couldn't find WHY this is the expected
behavior. I need to understand it.

[Bug c++/102577] New: Function frame size in relation to variables in conditional subscopes

2021-10-03 Thread krzyk240 at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102577

Bug ID: 102577
   Summary: Function frame size in relation to variables in
conditional subscopes
   Product: gcc
   Version: 11.1.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: krzyk240 at gmail dot com
  Target Milestone: ---

Consider the following code:
```
int bar(unsigned short x, int* cache = nullptr) {
if (!cache) {
int cache[1 << (sizeof(x) * 8)] = {};
return bar(x, cache);
}
if (cache[x] != 0) {
return cache[x];
}
if (x == 0) {
cache[x] = 1;
} else {
cache[x] = (bar(x - 1, cache) + bar(x / 2, cache)) % 17;
}
return cache[x];
}

int bar2(unsigned short x, int* cache = nullptr) {
if (!cache) {
return [&] {
int cache[1 << (sizeof(x) * 8)] = {};
return bar2(x, cache);
}();
}
if (cache[x] != 0) {
return cache[x];
}
if (x == 0) {
cache[x] = 1;
} else {
cache[x] = (bar2(x - 1, cache) + bar2(x / 2, cache)) % 17;
}
return cache[x];
}

#include 
#include 

int main() {
printf("%i\n", bar(65535));
system("grep Vm /proc/$PPID/status");
}
```

The only difference between functions bar() and bar2() the first if -- in
bar2() its contents are wrapped inside immediately invoked lambda.

What is important, on the first call to bar() or bar2(), a big local array will
be created on stack, and then in each recursive invocation, it will be not
created. So this big local array is created ONCE if we analyze the control
flow.

The depth of the recursion is x, and I assume sizeof(unsigned short) == 2. So
the program should use little memory (at most, a couple of MB).

Unfortunately this program consumes much more memory than expected, VmRSS is
around 270 MB, and VmStk is around 16 GB. Invoking it compiled with O2 (g++
abc.cc -O2 -o abc), produces:
```
964369483
VmPeak: 16787136 kB
VmSize: 16787100 kB
VmLck: 0 kB
VmPin: 0 kB
VmHWM:269272 kB
VmRSS:269272 kB
VmData:  240 kB
VmStk:  16781320 kB
VmExe: 4 kB
VmLib:  3188 kB
VmPTE: 32892 kB
VmSwap:0 kB
```

If we change invocation `bar(65535)` to `bar2(65535)` it produces:
```
964369483
VmPeak: 9148 kB
VmSize: 9112 kB
VmLck: 0 kB
VmPin: 0 kB
VmHWM:  6092 kB
VmRSS:  6092 kB
VmData:  240 kB
VmStk:  3332 kB
VmExe: 4 kB
VmLib:  3188 kB
VmPTE:56 kB
VmSwap:0 kB
```
Which are the expected numbers.

It seems that GCC propagates allocation of stack memory for the local array to
the function scope ignoring enclosing conditional scope. So that stack frame
size of bar() is always greater than 65536 * 4b. Clang seems behave in the same
way as GCC.

I tried to find some information why it is done this way, but failed to find
anything (I checked, cppreference, c++17 standard, stack overflow etc.). So
here is my question:
Is this behavior compliant with C++ standard, or is it a bug, or is it an
optimization that rarely has an adverse impact?

IMO, moving big stack memory allocations from conditional subscopes to function
scope, especially if this function is recursive is not a good idea. This
behavior was quite surprising for me when I discovered why similar program uses
(wastes) so much memory.

[Bug c++/100231] New: [C++17] Variable template specialization inside a class gives compilation error

2021-04-23 Thread krzyk240 at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100231

Bug ID: 100231
   Summary: [C++17] Variable template specialization inside a
class gives compilation error
   Product: gcc
   Version: 10.2.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: krzyk240 at gmail dot com
  Target Milestone: ---

On the following code:
```
template
struct X {};

class Foo {
template
static constexpr inline bool bar = false;
template
static constexpr inline bool bar> = true;
};
```
GCC gives error:
:8:34: error: explicit template argument list not allowed
8 | static constexpr inline bool bar> = true;
  |  ^

But Clang, ICC and MSVC compile it correctly.

Defining variable template bar outside of Foo class produces no compile errors.

Compilation command: g++ example.cpp -std=c++17

Live example: https://godbolt.org/z/54hqYxe4P

[Bug c++/91159] New: Compilation error on explicitly defaulting default constructor of abstract class with virtual base class

2019-07-13 Thread krzyk240 at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91159

Bug ID: 91159
   Summary: Compilation error on explicitly defaulting default
constructor of abstract class with virtual base class
   Product: gcc
   Version: unknown
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: krzyk240 at gmail dot com
  Target Milestone: ---

Consider the code below:

```
class Base {
public:
Base(int) {}

virtual void foo() = 0;

virtual ~Base() = default;
};

class A : virtual public Base {
public:
A() = default; // Works with this line commented out
};

class B : public A {
public:
B() : Base(0) {}

void foo() override {}
};

int main() {
B b;
}
```

It does not compile with GCC but compiles with Clang without problems. However,
that is a minor issue. The core issue is that with the line `A() = default;`
commented out, this code compiles fine on GCC.

So, the question is: Should be there such difference between implicitly
declared default constructor and explicitly defaulted default constructor?

If such code is anyhow wrong, what should be the correct way to write it? As I
understand, there is no point in making constructor of class A that initializes
the class Base. That is because Base class is virtually inherited and class A
is abstract. That means that A cannot be constructed directly and since the
most derivative class has to directly call the virtual base class constructor,
class A will never construct Base directly.

[Bug c++/70732] Operator new is unable to throw std::bad_alloc() when memory is exhausted in statically linked executable

2016-04-20 Thread krzyk240 at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70732

--- Comment #2 from Krzysztof Małysa  ---
I read some code from unwind-dw2-fde.c and it makes sense.

In the code above, stack unwinding happens in low memory conditions which
causes unsuccessful memory allocations and because of deep recursion, there are
so many of them.

But maybe it is reasonable to make an optimization to not flood system with
many, many unsuccessful syscalls (brk() and mmap2()). It's important to note
that stack unwinding happens at the bottom of recursion (so it's unlikely that
there will be more memory available - see
https://github.com/gcc-mirror/gcc/blob/master/libgcc/unwind-dw2-fde.c#L957),
also look at these syscalls which malloc makes:
brk(0xcad8000) = 0xcab4000
mmap2(NULL, 1048576, ...) = -1
It tries to expand stack (which is not successful due to deep recursion that
was made) and to map 1MB of memory, what is very much compared to what is
needed, so it will almost always result in malloc() returning NULL. That is why
it doesn't make much sense to call malloc() all the time if there is no memory
available while we're freeing only small chunks of memory.

All in all, I agree that there is no bug, but I think that it's a good
opportunity to make an optimization here.

[Bug c++/70732] New: Operator new is unable to throw std::bad_alloc() when memory is exhausted in statically linked executable

2016-04-19 Thread krzyk240 at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70732

Bug ID: 70732
   Summary: Operator new is unable to throw std::bad_alloc() when
memory is exhausted in statically linked executable
   Product: gcc
   Version: 5.3.0
Status: UNCONFIRMED
  Severity: major
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: krzyk240 at gmail dot com
  Target Milestone: ---

Created attachment 38313
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=38313&action=edit
*.ii file

When there is no more memory available for the program and operator new is
called, then it is unable to throw an exception - it unsuccessfully tries
several times (a couple of thousands) to allocate memory for the exception. And
finally, the exception is thrown. The problem is that memory for the exception
is tried to be allocated too many times, but only if the program is statically
linked. I have done some research and found that numerous allocation attempts
come from function _Unwind_RaiseException(). To see unsuccessful allocation
attempts, use command Strace. And one more thing I tested this program on GCC
4.6.4, 4.7.3, 4.8.5, 4.9.3, 5.3.0 and only on version 4.6.3 number of calls to
brk(2) and mmap2() was normal (no more than 100).

Here is code which is supossed to trigger the problem:
#include 

void foo(int k) {
const int size1 = 64;
const int size2 = 256;
volatile int t[size1];

// new[] should throw an exception as soon as memory is exhausted
int volatile* p = new int[size2];
t[size1 - 1] = p[size2 - 1] = ++k; // prevent compiler from erasing t
and p
foo(++k);
}

int main() {
// Set low memory limit
struct rlimit limit;
limit.rlim_cur = limit.rlim_max = 10 << 20;
if (setrlimit(RLIMIT_AS, &limit))
return 1;
if (setrlimit(RLIMIT_STACK, &limit))
return 2;

foo(0);
return 0;
}
///

Compilation command and output:
$ g++-5 -v -save-temps -static re.cpp -o r -m32 -O2
Using built-in specs.
COLLECT_GCC=g++-5
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/5/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu
5.3.0-3ubuntu1~14.04' --with-bugurl=file:///usr/share/doc/gcc-5/README.Bugs
--enable-languages=c,ada,c++,java,go,fortran,objc,obj-c++ --prefix=/usr
--program-suffix=-5 --enable-shared --enable-linker-build-id
--libexecdir=/usr/lib --without-included-gettext --enable-threads=posix
--libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu
--enable-libstdcxx-debug --enable-libstdcxx-time=yes
--with-default-libstdcxx-abi=gcc4-compatible --disable-libstdcxx-dual-abi
--enable-gnu-unique-object --disable-vtable-verify --enable-libmpx
--enable-plugin --with-system-zlib --disable-browser-plugin
--enable-java-awt=gtk --enable-gtk-cairo
--with-java-home=/usr/lib/jvm/java-1.5.0-gcj-5-amd64/jre --enable-java-home
--with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-5-amd64
--with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-5-amd64
--with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar
--enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686
--with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib
--with-tune=generic --enable-checking=release --build=x86_64-linux-gnu
--host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 5.3.0 20151204 (Ubuntu 5.3.0-3ubuntu1~14.04) 
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-static' '-o' 'r' '-m32' '-O2'
'-mtune=generic' '-march=i686'
 /usr/lib/gcc/x86_64-linux-gnu/5/cc1plus -E -quiet -v -imultilib 32 -imultiarch
i386-linux-gnu -D_GNU_SOURCE re.cpp -m32 -mtune=generic -march=i686 -O2
-fpch-preprocess -fstack-protector -Wformat -Wformat-security -o re.ii
ignoring nonexistent directory
"/usr/lib/gcc/x86_64-linux-gnu/5/../../../../include/i386-linux-gnu/c++/5"
ignoring nonexistent directory "/usr/local/include/i386-linux-gnu"
ignoring nonexistent directory
"/usr/lib/gcc/x86_64-linux-gnu/5/../../../../x86_64-linux-gnu/include"
ignoring nonexistent directory "/usr/include/i386-linux-gnu"
#include "..." search starts here:
#include <...> search starts here:
 /usr/include/c++/5
 /usr/include/x86_64-linux-gnu/c++/5/32
 /usr/include/c++/5/backward
 /usr/lib/gcc/x86_64-linux-gnu/5/include
 /usr/local/include
 /usr/lib/gcc/x86_64-linux-gnu/5/include-fixed
 /usr/include
End of search list.
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-static' '-o' 'r' '-m32' '-O2'
'-mtune=generic' '-march=i686'
 /usr/lib/gcc/x86_64-linux-g

[Bug c++/70486] New: Constexpr array captured in lambda function (used via std::function)

2016-03-31 Thread krzyk240 at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70486

Bug ID: 70486
   Summary: Constexpr array captured in lambda function (used via
std::function)
   Product: gcc
   Version: 5.1.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: krzyk240 at gmail dot com
  Target Milestone: ---

Created attachment 38150
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=38150&action=edit
The *.i* file



#include 
#include 

int main() {
constexpr int t[2] = { 1, 2 };
std::function foo = [&] {
for (int i = 0; i < 2; ++i)
std::cout << t[i] << ' ';
};

foo();
return 0;
}



$ g++-5.1 -std=c++11 -Wall -Wextra main.cpp -v -save-temps

Using built-in specs.
COLLECT_GCC=g++-5.1
COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc/x86_64-unknown-linux-gnu/5.1.0/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with: ../gcc-5.1.0/configure --prefix=/usr/local --disable-multilib
--without-mpc --without-mpfr --without-gmp --without-cloog --without-isl
--enable-languages=c,c++
Thread model: posix
gcc version 5.1.0 (GCC) 
COLLECT_GCC_OPTIONS='-std=c++11' '-Wall' '-Wextra' '-v' '-save-temps'
'-shared-libgcc' '-mtune=generic' '-march=x86-64'
 /usr/local/libexec/gcc/x86_64-unknown-linux-gnu/5.1.0/cc1plus -E -quiet -v
-imultiarch x86_64-linux-gnu -D_GNU_SOURCE main.cpp -mtune=generic
-march=x86-64 -std=c++11 -Wall -Wextra -fpch-preprocess -o main.ii
ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
ignoring nonexistent directory
"/usr/local/lib/gcc/x86_64-unknown-linux-gnu/5.1.0/../../../../x86_64-unknown-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:

/usr/local/lib/gcc/x86_64-unknown-linux-gnu/5.1.0/../../../../include/c++/5.1.0

/usr/local/lib/gcc/x86_64-unknown-linux-gnu/5.1.0/../../../../include/c++/5.1.0/x86_64-unknown-linux-gnu

/usr/local/lib/gcc/x86_64-unknown-linux-gnu/5.1.0/../../../../include/c++/5.1.0/backward
 /usr/local/lib/gcc/x86_64-unknown-linux-gnu/5.1.0/include
 /usr/local/include
 /usr/local/lib/gcc/x86_64-unknown-linux-gnu/5.1.0/include-fixed
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.
COLLECT_GCC_OPTIONS='-std=c++11' '-Wall' '-Wextra' '-v' '-save-temps'
'-shared-libgcc' '-mtune=generic' '-march=x86-64'
 /usr/local/libexec/gcc/x86_64-unknown-linux-gnu/5.1.0/cc1plus -fpreprocessed
main.ii -quiet -dumpbase main.cpp -mtune=generic -march=x86-64 -auxbase main
-Wall -Wextra -std=c++11 -version -o main.s
GNU C++11 (GCC) version 5.1.0 (x86_64-unknown-linux-gnu)
compiled by GNU C version 5.1.0, GMP version 5.0.2, MPFR version
3.1.0-p3, MPC version 0.9
GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096
GNU C++11 (GCC) version 5.1.0 (x86_64-unknown-linux-gnu)
compiled by GNU C version 5.1.0, GMP version 5.0.2, MPFR version
3.1.0-p3, MPC version 0.9
GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096
Compiler executable checksum: 03db94ff6398330bffd2a80db4ec6941
main.cpp: In lambda function:
main.cpp:8:20: internal compiler error: in make_decl_rtl, at varasm.c:1313
std::cout << t[i] << ' ';
^
libbacktrace could not find executable to open
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://gcc.gnu.org/bugs.html> for instructions.



$ uname -a

Linux stacked-crooked 3.2.0-74-virtual #109-Ubuntu SMP Tue Dec 9 17:04:48 UTC
2014 x86_64 x86_64 x86_64 GNU/Linux