[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[debbugs-tracker] bug#18995: closed (Error: Could not reserve dynamic he

From: GNU bug Tracking System
Subject: [debbugs-tracker] bug#18995: closed (Error: Could not reserve dynamic heap area.)
Date: Sun, 09 Nov 2014 16:13:02 +0000

Your message dated Sun, 09 Nov 2014 18:12:16 +0200
with message-id <address@hidden>
and subject line Re: bug#18995: Error: Could not reserve dynamic heap area.
has caused the debbugs.gnu.org bug report #18995,
regarding Error: Could not reserve dynamic heap area.
to be marked as done.

(If you believe you have received this mail in error, please contact

18995: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=18995
GNU Bug Tracking System
Contact address@hidden with problems
--- Begin Message --- Subject: Error: Could not reserve dynamic heap area. Date: Sat, 8 Nov 2014 16:22:56 +0100
The build enviroment is MinGW-w64 and MSYS2.

When I build `emacs-24', Emacs is being configured with

Should Emacs use the GNU version of malloc? yes
Should Emacs use a relocating allocator for buffers? yes
Should Emacs use mmap(2) for buffer allocation? no

With this configuration the x64 version is built just fine, but the x86 version build fails with

make[2]: Entering directory '/c/Users/Haroogan/Projects/GitHub/MINGW-packages/mingw-w64-emacs/src/.build/i686-w64-mingw32/lisp'
Compiling /C/Users/Haroogan/Projects/GitHub/MINGW-packages/mingw-w64-emacs/src/emacs/lisp/emacs-lisp/macroexp.el
Error: Could not reserve dynamic heap area.

 I've checked what is called in this case and it seems to be fine at the first glance:

#else  /* USE_LSB_TAG */
static char *
allocate_heap (void)
#ifdef _WIN64
  size_t size = 0x4000000000ull; /* start by asking for 32GB */
  /* We used to start with 2GB here, but on Windows 7 that would leave
     too little room in the address space for threads started by
     Windows on our behalf, e.g. when we pop up the file selection
     dialog.  */
  size_t size = 0x68000000; /* start by asking for 1.7GB */ <<< This one is used.
  void *ptr = NULL;

  while (!ptr && size > 0x00100000)
      reserved_heap_size = size;
      ptr = VirtualAlloc (NULL,
 get_reserved_heap_size (),
      size -= 0x00800000; /* if failed, decrease request by 8MB */

  return ptr;
#endif /* USE_LSB_TAG */

Any ideas?

--- End Message ---
--- Begin Message --- Subject: Re: bug#18995: Error: Could not reserve dynamic heap area. Date: Sun, 09 Nov 2014 18:12:16 +0200
> Date: Sat, 08 Nov 2014 20:49:01 +0000
> From: Daniel Colascione <address@hidden>
> CC: address@hidden
> Alexander, does it help to add explicit debug output (say, fprintf to
> stderr) on each iteration of the loop?

I'm not Alexander, but I can answer that question now: no, it doesn't
help.  The loop is still executed only once, even if it calls fprintf.

> If not, can you compare the debug output from the version with
> -funroll-loops to the one without, to see whether we're making the
> same sequence of VirtualAlloc calls? If they're the same, maybe it's
> not the loop that's broken, but the address space layout.

There's nothing wrong with the address space, and there's nothing
wrong with GCC, either.  What we have here is a genuine bug in our
code, albeit one that is subtle, and also very hard to actually
reproduce in real life.

It looked like a GCC bug at first, but as I tried to modify the source
and look at the effect of that on the generated code, it finally
dawned on me: GCC's loop-unrolling code simply correctly calculated
that with the initial value of 0x68000000 and decrement of 0x00800000,
the value of 'size' in the loop will never be less than 0x00100000,
due to wraparound in the subtraction of unsigned values.  So what we
have here is a potentially infinite loop, i.e. "undefined behavior".
Given that, it is justified for GCC to give us what we deserve, i.e. a
loop "unrolled" by executing its body only once.  I present the
disassembly below, for the curious, and it's clear that there's no
loop there, and also the value of 'size' is never tested at all, since
GCC decided that the condition 'size > 0x00100000' is always true.

Of course, in reality this "infinite" loop will always be finite,
since a real live system will always find more than 8MB of free
address space to reserve.  Unless someone deliberately reserved a lot
of the address space just to cause Emacs hit this problem, that is.

I installed a trivial fix on the emacs-24 branch, and I'm closing this

Here's the disassembly of the original code, as compiled with
"-funroll-loops" (it is for init_heap, because allocate_heap is
inlined in it):

  (gdb) disassemble init_heap
  Dump of assembler code for function init_heap:
     0x0122f1fc <+0>:     push   %ebx
     0x0122f1fd <+1>:     sub    $0x18,%esp
     0x0122f200 <+4>:     movl   $0x0,(%esp)
     0x0122f207 <+11>:    call   0x1277184 <address@hidden>
     0x0122f20c <+16>:    sub    $0x4,%esp
     0x0122f20f <+19>:    add    0x3c(%eax),%eax
     0x0122f212 <+22>:    mov    %eax,0x4(%esp)
     0x0122f216 <+26>:    movl   $0x14c1cd0,(%esp)
     0x0122f21d <+33>:    call   0x11c4cb5 <find_section>
     0x0122f222 <+38>:    mov    %eax,0x154abd4
     0x0122f227 <+43>:    cmpl   $0x0,0x1533cf0
     0x0122f22e <+50>:    je     0x122f28b <init_heap+143>
     0x0122f230 <+52>:    mov    $0x68000000,%ecx
     0x0122f235 <+57>:    mov    %ecx,0x15422a0
     0x0122f23b <+63>:    movl   $0x1,0xc(%esp)
     0x0122f243 <+71>:    movl   $0x2000,0x8(%esp)
     0x0122f24b <+79>:    mov    %ecx,0x4(%esp)
     0x0122f24f <+83>:    movl   $0x0,(%esp)
     0x0122f256 <+90>:    call   0x12775cc <address@hidden>
     0x0122f25b <+95>:    sub    $0x10,%esp
     0x0122f25e <+98>:    mov    %eax,0x15422ac
     0x0122f263 <+103>:   test   %eax,%eax                  <<<<<<<<<<<
     0x0122f265 <+105>:   jne    0x122f27f <init_heap+131>  <<<<<<<<<<<
     0x0122f267 <+107>:   movl   $0x14c1cd8,(%esp)          <<<<<<<<<<<
     0x0122f26e <+114>:   call   0x122f0e0 <printf>         <<<<<<<<<<<
     0x0122f273 <+119>:   movl   $0x1,(%esp)                <<<<<<<<<<<
     0x0122f27a <+126>:   call   0x1276948 <exit>           <<<<<<<<<<<
     0x0122f27f <+131>:   mov    %eax,0x15422a8
     0x0122f284 <+136>:   mov    %eax,0x15422a4
     0x0122f289 <+141>:   jmp    0x122f2bc <init_heap+192>
     0x0122f28b <+143>:   mov    0xc(%eax),%ebx
     0x0122f28e <+146>:   movl   $0x0,(%esp)
     0x0122f295 <+153>:   call   0x1277184 <address@hidden>
     0x0122f29a <+158>:   sub    $0x4,%esp
     0x0122f29d <+161>:   add    %ebx,%eax
     0x0122f29f <+163>:   mov    %eax,0x15422ac
     0x0122f2a4 <+168>:   mov    %eax,0x15422a8
     0x0122f2a9 <+173>:   mov    %eax,0x15422a4
     0x0122f2ae <+178>:   mov    0x154abd4,%eax
     0x0122f2b3 <+183>:   mov    0x8(%eax),%edx
     0x0122f2b6 <+186>:   mov    %edx,0x15422a0
     0x0122f2bc <+192>:   call   0x1201f1d <cache_system_info>
     0x0122f2c1 <+197>:   add    $0x18,%esp
     0x0122f2c4 <+200>:   pop    %ebx
     0x0122f2c5 <+201>:   ret
  End of assembler dump.

Look, ma: no loop!

--- End Message ---

reply via email to

[Prev in Thread] Current Thread [Next in Thread]