jeudi 1 octobre 2015

c++ system call raises ENOMEM

This question is a M(not)WE of this question. I wrote a code that reproduces the error :

#include <cstdlib>
#include <iostream>
#include <vector>

int *watch_errno = __errno_location();

int main(){
    std::vector<double> a(7e8,1);
    std::cout<<system(NULL)<<std::endl;
}

It has to be compiled with g++ -ggdb -std=c++11 (g++ 4.9 on a Debian). Note that the int *watch_errno is only usefull to allow gdb to watch errno. When it is run trough gdb, I get this :

GNU gdb (Debian 7.7.1+dfsg-5) 7.7.1
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://ift.tt/KpOJT7;
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://ift.tt/xLrliR;.
Find the GDB manual and other documentation resources online at:
<http://ift.tt/1gENejF;.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from bug...done.
(gdb) watch *watch_errno 
Hardware watchpoint 1: *watch_errno
(gdb) r
Starting program: /tmp/bug 
Hardware watchpoint 1: *watch_errno

Old value = <unreadable>
New value = 0
__static_initialization_and_destruction_0 (__initialize_p=1, __priority=65535) at bug.cpp:10
10      }
(gdb) c
Continuing.
Hardware watchpoint 1: *watch_errno

Old value = 0
New value = 12
0x00007ffff7252421 in do_system (line=line@entry=0x7ffff7372168 "exit 0") at ../sysdeps/posix/system.c:116
116     ../sysdeps/posix/system.c: No such file or directory.
(gdb) bt
#0  0x00007ffff7252421 in do_system (line=line@entry=0x7ffff7372168 "exit 0") at ../sysdeps/posix/system.c:116
#1  0x00007ffff7252510 in __libc_system (line=<optimized out>) at ../sysdeps/posix/system.c:182
#2  0x0000000000400ad8 in main () at bug.cpp:9
(gdb) l
111     in ../sysdeps/posix/system.c
(gdb) c
Continuing.
0
[Inferior 1 (process 5210) exited normally]

For some reason errno is set to ENOMEM at line 9 which corresponds to the system call. Note that if the vector has a smaller size (I guess that it depends on which computer you'll run the code), the code works fine and system(NULL) returns 1 as it should when a shell is available.

Why is the flag ENOMEM raised ? Why isn't the code using the SWAP memory ? Is this a bug ? Is there a workaround ? Would popen or exec* do the same ? (I know, I should only ask one question per post, but all these question could be summarized by : "what is going on ?")

Aucun commentaire:

Enregistrer un commentaire