It appears that your SHELL variable is set to a file that doesn't exist. Try the following:
export SHELL=/bin/sh
gdb test
ensuring that /bin/sh
exists and is executable. This works via su
not because of root permissions, but because su
resets the SHELL
environment variable. Per the su manual page:
Note that the default behavior for the environment is the following:
The $HOME, $SHELL, $USER, $LOGNAME, $PATH, and $IFS environment variables are reset.
Further Discussion
If you are asking yourself, "How was I supposed to know that from the following error message?":
//error: Cannot exec /home/xxx/test/test -c exec /home/xxx/test/test .
//Error: No such file or directory
You are not alone. This appears to be poor error reporting from gdb
. When gdb
decides that it needs to execute your command using a shell, it constructs a command in the following format:
/path/to/shell -c exec /path/to/executable
However, when it prints the error message, it does this:
save_errno = errno;
fprintf_unfiltered (gdb_stderr, "Cannot exec %s", exec_file);
for (i = 1; argv[i] != NULL; i++)
fprintf_unfiltered (gdb_stderr, " %s", argv[i]);
fprintf_unfiltered (gdb_stderr, ".\n");
fprintf_unfiltered (gdb_stderr, "Error: %s\n",
safe_strerror (save_errno));
gdb_flush (gdb_stderr);
Here exec_file
is the expanded path of the file you passed on the command line. It prints exec_file
first, followed by the elements of argv
, starting at the 1st index. argv
contains the arguments it passed to execvp
.
Unfortunately, the shell it is trying to use is in the 0th element of argv
, which never gets printed. Thus, you never see the file that execvp
couldn't find.
Further, it then prints a trailing .
which isn't actually one of the arguments that it passed to execvp
and is presumably there to make the message a completely sentence.
Finally, it prints the error we got back from our call to execvp
, which is that the executable file could not be found.
This bug likely is caused by the fact that this error handling code is the same for the case where gdb
attempts to exec the command directly and for the case when it uses the shell. In the former case, the constructed error message would look correct since exec_file
and argv[0]
would be the same.
Chip's answer was helpful, however since the SET
line overwrote CMAKE_CXX_FLAGS_DEBUG
this removed the -g
default which caused my executable to be built without debug info. I needed to make a small additional modification to CMakeLists.txt in the project source directory to get an executable built with debugging info and -O0
optimizations (on cmake version 2.8.12.2).
I added the following to CMakeLists.txt to add -O0
and leave -g
enabled:
# Add -O0 to remove optimizations when using gcc
IF(CMAKE_COMPILER_IS_GNUCC)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0")
ENDIF(CMAKE_COMPILER_IS_GNUCC)
This adds the -O0
optimization to flags already used for debug by CMake and only is included for GCC builds if you happen to be using a cross platform project.
Best Answer
I think you can use the trick.
set the break point in exit.
gdb ..
b exit
run ..
bt
so you can know where the main call the exit funciton