1

コンピューターから root として実行すると C++ プログラムでセグ フォールトが発生しますが、リモート セッションを開始すると発生しません。私のプログラムは、ユーザーとしてのみコンピューターから実行されます。何が問題になる可能性がありますか? 組み込みデバイス用のプログラムを作成し、これを使用してコンパイルしています。

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

バックトレースはこれを与えます:

(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;
}

編集:問題は解決しました。プログラムには、端末の env に DBUS_SESSION_ADDRESS が必要です。

4

4 に答える 4

6

問題は、どこかで未定義の動作を呼び出したことです。未定義の動作は、異なるマシンで異なる動作をする可能性があり、同じマシンで異なる実行を行う可能性があります。ワイルドポインタを発生させる場所を見つけて、それに対処する必要があります。

制限付きユーザーとして実行しているときに「幸運」になっている可能性があります。プロセスのページ権限が、取得している無効なメモリアクセスを許可するように設定されているか、ルート固有のコードがありません。ユーザーモードでのみ実行すると到達します。

于 2011-06-03T23:41:04.467 に答える
4

の下でプログラムを実行したい場合があります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;
}

知っておくと便利なもう 1 つのツールは、 ですgdb。コアのダンプを許可するように rlimits を設定すると (setrlimit(2)制限の詳細については を、組み込みコマンドの詳細についてはシェルのマニュアル (おそらくbash(1)) を参照してくださいulimit)、次のコマンドで使用するコア ファイルを取得できます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 に到達するための呼び出しチェーンを知ることは重要な情報になる可能性があります。

于 2011-06-03T23:58:45.073 に答える
2

コードを見ずに具体的なことを言うのは難しいので、一般的なアドバイスをいくつか紹介します。デバッガー (おそらく gdb) の使い方を学び、デバッガーで失敗を再現してみてください。運が良ければ、セグメンテーション違反はデバッガーで引き続き発生し、失敗した場所を示すスタック トレースが得られます。これにより、問題の真の原因に戻るための出発点が得られます。 .

運が悪い場合は、デバッグ サポートを使用してコンパイルするか、gdb で実行すると、問題がなくなる可能性があります。その場合、コード検査に頼る必要があり、未定義の動作 (たとえば、Billy ONeal が示唆するように、ワイルドまたは初期化されていないポインター) についてコードをスクラブする必要があります。

于 2011-06-03T23:53:25.450 に答える
2

設定しulimit -c unlimitedます。

プログラムを実行し、クラッシュさせます。これでコア ダンプが発生するはずです。

走るgdb <program-name> core

(backtrace) コマンドを使用するbtと、クラッシュが発生している場所がわかります。これは、それを修正するのに役立ちます。

于 2011-06-04T00:09:50.203 に答える