Cette question est un M(not)WE de cette question. J'ai écrit un code qui reproduit l'erreur:C++ système() soulève ENOMEM
#include <cstdlib>
#include <iostream>
#include <vector>
int *watch_errno = __errno_location();
int main(){
std::vector<double> a(7e8,1); // allocate a big chunk of memory
std::cout<<system(NULL)<<std::endl;
}
Il doit être compilé avec g++ -ggdb -std=c++11
(g ++ 4.9 sur Debian). Notez que le int *watch_errno
est utile uniquement pour permettre à gdb de regarder errno
.
Lorsqu'il est exécuté sous gdb
, je reçois ceci:
(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 ([email protected]=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 ([email protected]=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]
Pour une raison quelconque errno
est réglé sur ENOMEM
à la ligne 9, qui correspond à la system()
appel. Notez que si le vecteur a une taille plus petite (je suppose que dépend de l'ordinateur sur lequel vous allez exécuter le code), le code fonctionne bien et system(NULL)
renvoie 1 comme il se doit lorsqu'un shell est disponible.
Pourquoi le drapeau ENOMEM
est-il surélevé? Pourquoi le code n'utilise-t-il pas la mémoire d'échange? Est-ce un bug? Y at-il un travail autour? Est-ce que popen
ou exec*
feraient la même chose? (Je sais, je ne devrais poser une question par courrier, mais toutes ces questions pourraient se résumer par « ce qui se passe? »)
Comme demandé, voici le résultat de ulimit -a
:
-t: cpu time (seconds) unlimited
-f: file size (blocks) unlimited
-d: data seg size (kbytes) unlimited
-s: stack size (kbytes) 8192
-c: core file size (blocks) 0
-m: resident set size (kbytes) unlimited
-u: processes 30852
-n: file descriptors 65536
-l: locked-in-memory size (kbytes) 64
-v: address space (kbytes) unlimited
-x: file locks unlimited
-i: pending signals 30852
-q: bytes in POSIX msg queues 819200
-e: max nice 0
-r: max rt priority 0
-N 15: unlimited
et ici la partie pertinente de strace -f myprog
mmap(NULL, 5600002048, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7faa98562000
rt_sigaction(SIGINT, {SIG_IGN, [], SA_RESTORER, 0x7fabe622b180}, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGQUIT, {SIG_IGN, [], SA_RESTORER, 0x7fabe622b180}, {SIG_DFL, [], 0}, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
clone(child_stack=0, flags=CLONE_PARENT_SETTID|SIGCHLD, parent_tidptr=0x7fff8797635c) = -1 ENOMEM (Cannot allocate memory)
rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7fabe622b180}, NULL, 8) = 0
rt_sigaction(SIGQUIT, {SIG_DFL, [], SA_RESTORER, 0x7fabe622b180}, NULL, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fabe6fde000
write(1, "0\n", 20
) = 2
write(1, "8\n", 28
) = 2
munmap(0x7faa98562000, 5600002048) = 0
est ici la sortie du libre:
total used free shared buffers cached
Mem: 7915060 1668928 6246132 49576 34668 1135612
-/+ buffers/cache: 498648 7416412
Swap: 2928636 0 2928636
Vous devriez utiliser [strace (1)] (http://man7.org/linux/man- pages/man1/strace.1.html) sur votre programme. –
Le titre est un peu trompeur, car la question est liée à l'appel de la fonction 'system()', qui est différente d'un _system call_. – Michael
Est-ce sur une plate-forme 64 bits? –