Ошибка сегментации при запуске от имени пользователя root? - PullRequest
1 голос
/ 04 июня 2011

Моя программа на С ++ выдает ошибку при сегментировании, когда я запускаю root с моего компьютера, но не при запуске удаленного сеанса. Моя программа запускается с моего компьютера только как пользователь. В чем может быть проблема? Я написал свою программу для встроенного устройства и использую ее для компиляции:

gcc -Werror notify.cc -o notify `pkg-config --libs --cflags gtk+-2.0 hildon-notifymm hildonmm hildon-fmmm'

Я не получаю никакой ошибки. Это может быть проблема с флагом? Я могу опубликовать свой код.

РЕДАКТИРОВАТЬ: Когда я запускаю программу с GDB, я получаю это:

Program received signal SIGSEGV, Segmentation fault.
0x40eed060 in strcmp () from /lib/libc.so.6
0x40eed060 <strcmp+0>:  ldrb    r2, [r0], #1

Backtrace дает это:

(gdb) backtrace
 #0  0x40eed060 in strcmp () from /lib/libc.so.6
 #1  0x40b7f190 in dbus_set_g_error ()
 from /usr/lib/libdbus-glib-1.so.2
 #2  0x40b7d060 in dbus_g_bus_get () from /usr/lib/libdbus-glib-1.so.2
 #3  0x400558ec in notify_init () from /usr/lib/libnotify.so.1
 #4  0x4004a240 in Notify::init(Glib::ustring const&) ()
 from /usr/lib/libnotifymm-1.0.so.7
 #5  0x40033794 in Hildon::notify_init(Glib::ustring const&) ()
 from /usr/lib/libhildon-notifymm-1.0.so.1

Вот мой код:

#include <hildonmm.h>
#include <hildon-notifymm.h>
#include <hildon/hildon-notification.h>
#include <libnotifymm/init.h>
#include <gtkmm/stock.h>
#include <dbus/dbus.h>
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
#include <iostream>

int main(int argc, char *argv[])
{
// Initialize gtkmm and maemomm:

Hildon::init();
Hildon::notify_init("Notification Example");

// Initialize D-Bus (needed by hildon-notify):
DBusConnection* conn = dbus_bus_get(DBUS_BUS_SESSION, NULL);
dbus_connection_setup_with_g_main(conn, NULL);

// Create a new notification:
Glib::RefPtr<Hildon::Notification> notification =   Hildon::Notification::create("Something Happened", "A thing has just happened.", Gtk::Stock::OPEN);

// Show the notification:
std::auto_ptr<Glib::Error> ex;
notification->show(ex);
if(ex.get())
{ 
std::cerr << "Notification::show() failed: " << ex->what() << std::endl;
}
return 0;
}

РЕДАКТИРОВАТЬ: Проблема решена. Программа нуждается в DBUS_SESSION_ADDRESS в env терминала.

Ответы [ 4 ]

6 голосов
/ 04 июня 2011

Проблема в том, что вы вызвали неопределенное поведение где-то.Неопределенное поведение может вести себя по-разному на разных машинах, разные прогоны на одной машине, что угодно.Вы должны найти, где вы позволяете использовать дикий указатель, и справиться с ним.

Скорее всего, вам просто «везет», когда вы работаете как пользователь с ограниченными правами, и установлены разрешения для страницы вашего процессачтобы разрешить любой недопустимый доступ к памяти, который вы получаете, или у вас есть какой-то специфический для root код, который недоступен при запуске только в пользовательском режиме.

4 голосов
/ 04 июня 2011

Возможно, вы захотите запустить вашу программу под valgrind.Я написал крошечную программу, которая пишет вне выделенного массива:

$ valgrind ./segfault
==11830== Memcheck, a memory error detector
==11830== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==11830== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==11830== Command: ./segfault
==11830== 
==11830== Invalid write of size 1
==11830==    at 0x4004BF: main (in /tmp/segfault)
==11830==  Address 0x7feff65bf is not stack'd, malloc'd or (recently) free'd
==11830== 
==11830== 
==11830== Process terminating with default action of signal 11 (SIGSEGV)
==11830==  Access not within mapped region at address 0x7FEFF65BF
==11830==    at 0x4004BF: main (in /tmp/segfault)
==11830==  If you believe this happened as a result of a stack
==11830==  overflow in your program's main thread (unlikely but
==11830==  possible), you can try to increase the size of the
==11830==  main thread stack using the --main-stacksize= flag.
==11830==  The main thread stack size used in this run was 8388608.
==11830== 
==11830== HEAP SUMMARY:
==11830==     in use at exit: 0 bytes in 0 blocks
==11830==   total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==11830== 
==11830== All heap blocks were freed -- no leaks are possible
==11830== 
==11830== For counts of detected and suppressed errors, rerun with: -v
==11830== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)
Segmentation fault

Самая важная часть этого вывода здесь:

==11830== Invalid write of size 1
==11830==    at 0x4004BF: main (in /tmp/segfault)

write of size 1 может помочь вам выяснитькакая строка была задействована:

int main(int argc, char *argv[]) {
    char f[1];
    f[-40000]='c';
    return 0;
}

Другой очень полезный инструмент, который нужно знать, это gdb.Если вы установили в rlimits разрешение на дамп ядра (подробности об ограничениях см. В setrlimit(2), а в подробностях о встроенной команде ulimit - в руководстве по вашей оболочке (вероятно, bash(1))), тогда вы можете получить файл ядраиспользуйте с gdb:

$ ulimit -c 1000
$ ./segfault 
Segmentation fault (core dumped)
$ gdb --core=core ./segfault
GNU gdb (GDB) 7.2-ubuntu
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
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".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /tmp/segfault...(no debugging symbols found)...done.
[New Thread 11951]

warning: Can't read pathname for load map: Input/output error.
Reading symbols from /lib/libc.so.6...Reading symbols from /usr/lib/debug/lib/libc-2.12.1.so...done.
done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib64/ld-linux-x86-64.so.2...Reading symbols from /usr/lib/debug/lib/ld-2.12.1.so...done.
done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
Core was generated by `./segfault'.
Program terminated with signal 11, Segmentation fault.
#0  0x00000000004004bf in main ()
(gdb) bt
#0  0x00000000004004bf in main ()
(gdb) quit

В зависимости от размера вашей программы вам может потребоваться уступить более чем 1000 блокам разрешенному файлу ядра.Если бы эта программа была удаленно сложной, знание цепочки вызовов, чтобы добраться до segfault, могло бы стать важной информацией.

2 голосов
/ 04 июня 2011

Set ulimit -c unlimited.

Запустите вашу программу и дайте ей сбой.Теперь он должен выполнять дамп памяти.

Выполнить gdb <program-name> core

Если вы используете команду bt (backtrace), это должно дать вам хорошее представление о том, где происходит сбой.Это должно помочь вам исправить это.

2 голосов
/ 04 июня 2011

Трудно сказать что-то конкретное, не видя никакого кода, поэтому я дам вам некоторые общие совет: научитесь использовать отладчик (вероятно, gdb) и попытайтесь воспроизвести ошибку под отладчиком. Если вам повезет, segfault все равно будет происходить под отладчиком, вы получите трассировку стека, показывающую, где он вышел из строя, и это даст вам отправную точку, которая позволит вам вернуться к истинному источнику проблемы.

Если вам не повезло, проблема может исчезнуть, если вы скомпилируете с поддержкой отладки, или запустить его под GDB. В этом случае вам придется прибегнуть к проверке кода и очистить свой код для любого неопределенного поведения (например, дикие или неинициализированные указатели, как Билли ОНил предлагает).

...