Устранение неполадок при сегментации - PullRequest
2 голосов
/ 19 февраля 2010

Я получаю ошибку сегментации в некотором C-коде, и я не могу понять, как это прочитать, чтобы я мог выяснить проблему ..

У кого-нибудь есть какие-нибудь техники, которые могут мне помочь? Вам что-нибудь выпрыгивает?

Вот вывод gdb:

GNU gdb 6.8 for GNAT Pro 6.2.1 (20090115) [rev:143235]
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
This is free software: you are free to change and redistribute it.
See your support agreement for details of warranty and support.
If you do not have a current support agreement, then there is absolutely
no warranty for this version of GDB.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "sparc-sun-solaris2.8"...
Reading symbols from /usr/lib/libsocket.so.1...done.
Loaded symbols for /usr/lib/libsocket.so.1
Reading symbols from /usr/lib/libnsl.so.1...done.
Loaded symbols for /usr/lib/libnsl.so.1
Reading symbols from /usr/lib/libgen.so.1...done.
Loaded symbols for /usr/lib/libgen.so.1
Reading symbols from /usr/lib/libintl.so.1...
warning: Lowest section in /usr/lib/libintl.so.1 is .dynamic at 00000074
done.
Loaded symbols for /usr/lib/libintl.so.1
Reading symbols from /usr/lib/libw.so.1...
warning: Lowest section in /usr/lib/libw.so.1 is .dynamic at 00000074
done.
Loaded symbols for /usr/lib/libw.so.1
Reading symbols from /usr/lib/libm.so.1...done.
Loaded symbols for /usr/lib/libm.so.1
Reading symbols from /opt/services/AZJCommonZJX/solaris/lib/libazjcommonjcxC.so...done.
Loaded symbols for /opt/services/AZJCommonZJX/solaris/lib/libazjcommonjcxC.so
Reading symbols from /usr/openwin/lib/libXext.so.0...done.
Loaded symbols for /usr/openwin/lib/libXext.so.0
Reading symbols from /usr/openwin/lib/libX11.so.4...done.
Loaded symbols for /usr/openwin/lib/libX11.so.4
Reading symbols from /usr/openwin/lib/libXmu.so.4...done.
Loaded symbols for /usr/openwin/lib/libXmu.so.4
Reading symbols from /usr/openwin/lib/libXt.so.4...done.
Loaded symbols for /usr/openwin/lib/libXt.so.4
Reading symbols from /usr/dt/lib/libXm.so.3...done.
Loaded symbols for /usr/dt/lib/libXm.so.3
Reading symbols from /usr/lib/libc.so.1...done.
Loaded symbols for /usr/lib/libc.so.1
Reading symbols from /opt/services/AZJCommonWork/solaris/lib/libazjcommonwork.so...done.
Loaded symbols for /opt/services/AZJCommonWork/solaris/lib/libazjcommonwork.so
Reading symbols from /opt/services/AZJCommonWork/solaris/lib/libazjcommonworkC.so...done.
Loaded symbols for /opt/services/AZJCommonWork/solaris/lib/libazjcommonworkC.so
Reading symbols from /app/gnatpro6.2.1/lib/gcc/sparc-sun-solaris2.8/4.3.3/rts-native/adalib/libgnarl-6.2.so...done.
Loaded symbols for /opt/tools/SunOS/gnatpro6.2.1/lib/gcc/sparc-sun-solaris2.8/4.3.3/adalib/libgnarl-6.2.so
Reading symbols from /app/gnatpro6.2.1/lib/gcc/sparc-sun-solaris2.8/4.3.3/rts-native/adalib/libgnat-6.2.so...done.
Loaded symbols for /opt/tools/SunOS/gnatpro6.2.1/lib/gcc/sparc-sun-solaris2.8/4.3.3/adalib/libgnat-6.2.so
Reading symbols from /usr/lib/libpthread.so.1...
warning: Lowest section in /usr/lib/libpthread.so.1 is .dynamic at 00000074
done.
Loaded symbols for /usr/lib/libpthread.so.1
Reading symbols from /usr/lib/librt.so.1...done.
Loaded symbols for /usr/lib/librt.so.1
Reading symbols from /app/gnatpro6.2.1/lib/libstdc++.so.6...done.
Loaded symbols for /opt/tools/SunOS/gnatpro6.2.1/lib/libstdc++.so.6
Reading symbols from /app/gnatpro6.2.1/lib/libgcc_s.so.1...done.
Loaded symbols for /opt/tools/SunOS/gnatpro6.2.1/lib/libgcc_s.so.1
Reading symbols from /usr/lib/libthread.so.1...
warning: Lowest section in /usr/lib/libthread.so.1 is .dynamic at 00000074
done.
Loaded symbols for /usr/lib/libthread.so.1
Reading symbols from /usr/lib/libaio.so.1...done.
Loaded symbols for /usr/lib/libaio.so.1
Reading symbols from /usr/lib/libmd.so.1...done.
Loaded symbols for /usr/lib/libmd.so.1
Reading symbols from /usr/lib/libm.so.2...done.
Loaded symbols for /usr/lib/libm.so.2
Reading symbols from /platform/sun4v/lib/libc_psr.so.1...done.
Loaded symbols for /platform/SUNW,Sun-Fire-T200/lib/libc_psr.so.1
Reading symbols from /lib/ld.so.1...done.
Loaded symbols for /lib/ld.so.1
Core was generated by `./solaris/apsui -aps_instance 1006 -aps_ato 0 -reject_menu_tearoff -aps_ipc_'.
Program terminated with signal 11, Segmentation fault.
[New process 75224    ]
#0  0x7f1e4d00 in _XmGetFocusData () from /usr/dt/lib/libXm.so.3

Вот что показывает полная трассировка GDB:

(gdb) bt full
#0  0x7f1e4d00 in _XmGetFocusData () from /usr/dt/lib/libXm.so.3
No symbol table info available.
#1  0x7f1e2768 in _XmNavigInitialize () from /usr/dt/lib/libXm.so.3
No symbol table info available.
#2  0x7f1e8adc in Initialize () from /usr/dt/lib/libXm.so.3
No symbol table info available.
#3  0x7f357760 in CallInitialize () from /usr/openwin/lib/libXt.so.4
No symbol table info available.
#4  0x7f3576b4 in CallInitialize () from /usr/openwin/lib/libXt.so.4
No symbol table info available.
#5  0x7f3576b4 in CallInitialize () from /usr/openwin/lib/libXt.so.4
No symbol table info available.
#6  0x7f353804 in xtCreate () from /usr/openwin/lib/libXt.so.4
No symbol table info available.
#7  0x7f35bf0c in _XtCreateWidget () from /usr/openwin/lib/libXt.so.4
No symbol table info available.
#8  0x7f35bc8c in XtCreateWidget () from /usr/openwin/lib/libXt.so.4
No symbol table info available.
#9  0x7f6026f8 in create_my_window (win=0xd3bc0)
    at /opt/services/AZJCommonZJX/src/uim/create/create_my_window.c:180
    n_args = 0
    args = {{name = 0x0, value = 0} }
    err_msg = '\0' , "ÿ¿Ïä", '\0' , "main_window_menu\000T_CMD MARITIME_TGT_CMD TEST \000K1\177}al\000\000\000\004\000\000\000\001\000\000\000\000"...
    shell = (Widget) 0xd50b8
    object_width = 0
    object_height = 1660944384
    window_name = "TBM_PrimaryWin\000ä\000\000\000\000\177ÿÿø\177ÿü\000\177\023\222¤\000\000 \000\000\f\215ð\000\f\217 \177\023\222¬\177ÿü\000\000\000\000\000ÿ¿Î\200\177\005f,\000\000\000\000\177\023Vx\000\fO \000\aÀ\020\000\fO \1772*\000ui_ipc_xref."
    icon_pixmap = 8332422
    obj = (gen_obj_list_t *) 0x6b0
    vis = (vis_list_t *) 0x7f832bb8
    toolbar = (toolbar_t *) 0x0
#10 0x7f5f524c in create_my_window (in_buff=0x19750 "main_window_menu")
    at /opt/services/AZJCommonZJX/src/uim/create/create_my_window.c:431
    func_name = "create_my_window"
    str = "\000\000\000\000\000\000\000\000¿¿Ä6'yC \000\000\000\000\000\000\000\000\177\235p0\000\000\000\000\000\003eÈ\000\003e¸\000\000\000\004ÿÿ\000\000\000\000\000\000ÿÿÿß\000\000\000\017\000\000\000\017\000\003^\200ÿ¿Ô\000\000\000\000\000\000\000\000\001\000\000\000\004\000\000\000\017ÿ¿Ó \177\2133, "\001\000\000\000\234\000\000\000\000\000\000\000\036\000\000\000\000\000\rP\000ÿ¿Ô \177\213\022\020\000"...
    ptr = 0x19760 ""
    keyword = 0x8a130 ""
    window_name = 0x8a130 ""
---Type  to continue, or q  to quit---
    title_name = "\000¿ÒØ\177\211îÄ\000\000\000\000\000\000\000\004", '\0' , "\003e¸\000\000\000\004ÿÿ\000\000\000\000\000\000ÿÿÿß\000\000\000\017\000\000\000 \000\001\023T\177¿sÈ\177·\fà\005øص\000\000\000@\177·\020Xÿ¿Ó8"
    full_title_name = 0x2b870 "TAP"
    object_width = 2141025804
    object_height = 1
    window_width = 0
    window_height = 0
    first_object = 1
    other_obj = 0
    centered_max_width = 18866798

Вот вывод dbx:

For information about new features see `help changes'
To remove this message, put `dbxenv suppress_startup_message 7.7' in your .dbxrc
Reading apsui
core file header read successfully
Reading ld.so.1
Reading libsocket.so.1
Reading libnsl.so.1
Reading libgen.so.1
Reading libintl.so.1
Reading libw.so.1
Reading libm.so.1
Reading librt.so.1
Reading libazjcommonjcxC.so
Reading libXext.so.0
Reading libX11.so.4
Reading libXmu.so.4
Reading libXt.so.4
Reading libXm.so.3
Reading libazjcommonwork.so
Reading libazjcommonworkC.so
Reading libgnarl-6.2.so
Reading libgnat-6.2.so
Reading libpthread.so.1
Reading libc.so.1
Reading libaio.so.1
Reading libmd.so.1
Reading libstdc++.so.6.0.10
Reading libgcc_s.so.1
Reading libthread.so.1
Reading libm.so.2
Reading libc_psr.so.1
t@1 (l@1) program terminated by signal SEGV (no mapping at the fault address)
0x7f264d00: _XmGetFocusData+0x0098: ld       [%o0], %o1
Current function is create_my_window
  180     win->main_window = MyWindow(shell, win->name, args, n_args);
>check -all
access checking - ON
memuse checking - ON
Running: apsui 
(process id 18052)
Reading rtcapihook.so
Reading libdl.so.1
Reading rtcaudit.so
Reading libmapmalloc.so.1
Reading rtcboot.so
Reading librtc.so
RTC: Enabling Error Checking...
RTC: Using UltraSparc trap mechanism
RTC: See `help rtc showmap' and `help rtc limitations' for details.
RTC: Running program...
azjcommonworkdummy.adb elaborated
 User Interface version TOOLKIT : 22 MAR 2010 UIMPID=18052
Read from unallocated (rua) on thread 1:
Attempting to read 4 bytes through NULL pointer
t@1 (l@1) stopped in _XmGetFocusData at 0x5d164d00
0x5d164d00: _XmGetFocusData+0x0098: ld       [%o0], %o1
Current function is create_my_window
  180     win->main_window = MyWindow(shell, win->name, args, n_args);

Вот последний вызов функции в трассировке стека, который я могу изменить (не во внешней библиотеке - в create_my_window) .. Полный код этого класса можно увидеть здесь: http://utilitybase.com/paste/26607

void create_my_window( window_t *win)
{
  Cardinal n_args;
  Arg      args[MAX_ARGS];

  Widget   shell = NULL;

//MORE STUFF HERE

  memset(&(args), 0, sizeof(Arg)*MAX_ARGS); n_args = 0;
  if (win->attributes != PRIMARY_WINDOW) {
    XtSetArg(args[n_args], XmNtopAttachment, XmATTACH_FORM); n_args++;
    XtSetArg(args[n_args], XmNbottomAttachment, XmATTACH_FORM); n_args++;
    XtSetArg(args[n_args], XmNleftAttachment, XmATTACH_FORM); n_args++;
    XtSetArg(args[n_args], XmNrightAttachment, XmATTACH_FORM); n_args++;
    XtSetArg(args[n_args], XmNtopOffset, 0); n_args++;
    XtSetArg(args[n_args], XmNbottomOffset, 0); n_args++;
    XtSetArg(args[n_args], XmNleftOffset, 0); n_args++;
    XtSetArg(args[n_args], XmNrightOffset, 0); n_args++;
  }
  win->main_window = XmCreateMainWindow(shell, win->name, args, n_args);

EDIT

Я добавил точку останова в gdb прямо перед вызовом функции и распечатал некоторые значения (не уверен, поможет ли это - я n00b):

Breakpoint 1, create_my_window (win=0x9b378)
    at /opt/services/AZJCommonZJX/src/jzs/create/create_my_window.c:179
179   printf("%d",n_args);
(gdb) p *win
$1 = {struct_type = 1045, next = 0x0, hash_name = 971, 
  name = 0x994e8 "error_log", widget = 0x0, main_window = 0x0, workarea = 0x0, 
  menu_bar = 0x0, message_window = 0x0, window_RC = 0x0, working_box = 0, 
  working_identifier = 0x0, has_message_area = 0, pos = {x = 0, y = 0}, 
  illegal_char_set = 0x0, height = 0, width = 0, configured = 0, 
  actions = 0x0, title = 0x99d18, help_text = 0x0, groups = 0x0, 
  scroll_bars = 0x0, write_protect = 0, attributes = 0, initial_focus = {
    obj_type = 0, obj_name = 0x0, area = 0x0}, text_edit = {
    text_selected_widget = 0x0, text_focus_widget = 0x0, updated_widget = 0x0, 
    start = 0, end = 0, updated_text = 0x0, last_operation = 0}, 
  close_rqt = 0x0, kill_application_action_list_name = 0x0, parent = 0x0, 
  gen_objs = 0x99da0, panes = 0x0, table_list = 0x0, selected_table = 0x0, 
  dialogs = 0x0, has_been_loaded = 0 '\0', source_file_name = 0x0}
(gdb) p *shell
$2 = {core = {self = 0x9db50, widget_class = 0xfec7897c, parent = 0x0, 
    xrm_name = 466, being_destroyed = 0 '\0', destroy_callbacks = 0x9ae58, 
    constraints = 0x0, x = 0, y = 0, width = 0, height = 0, border_width = 1, 
    managed = 0 '\0', sensitive = 1 '\001', ancestor_sensitive = 1 '\001', 
    event_table = 0x9ad98, tm = {translations = 0x0, proc_table = 0x0, 
      current_state = 0x0, lastEventTime = 0}, accelerators = 0x0, 
    border_pixel = 0, border_pixmap = 2, popup_list = 0x0, num_popups = 0, 
    name = 0x7776e "TBM_Dialog_Fixed", screen = 0x7a7e0, colormap = 32, 
    window = 0, depth = 24, background_pixel = 12825262, 
    background_pixmap = 2, visible = 1 '\001', mapped_when_managed = 1 '\001'}}
(gdb) p *args
$3 = {name = 0x0, value = 0}
(gdb) p *n_args
Cannot access memory at address 0x0
(gdb) p n_args
$4 = 0
(gdb) p args
$5 = {{name = 0x0, value = 0} <repeats 20 times>}

Ответы [ 9 ]

5 голосов
/ 23 февраля 2010

Учитывая, что dbx сказал: «Попытка прочитать 4 байта через указатель NULL», и что ошибка сообщалась в строке с вызовом функции, а не внутри функции XmCreateMainWindow, я предполагаю, что проблема связана с заявление win->name. Это единственное место в этой строке C, где вы будете читать из указателя до того, как функция будет фактически вызвана (она прочитает копию данных, хранящихся в win->name и передаст копию в функцию).

Попробуйте вставить следующее в строке сразу над вызовом XmCreateMainWindow

assert(win != NULL);

Вам нужно будет #include <assert.h>, если это еще не так. Это должно проверить, что win не является пустым указателем при вызове функции. Ради тщательности вы можете добавить аналогичную строку и для shell.

4 голосов
/ 20 февраля 2010

Ваш сбой происходит внутри libXm.Либо ваша куча была предварительно повреждена, либо вы передаете неверные данные (или, что гораздо менее вероятно, есть ошибка в libXm и / или других системных библиотеках).Аргументы выглядят нормально (хотя ваш набор настроек немного нестандартен).

Для проверки на повреждение кучи используйте Valgrind , но я не уверен, что он доступен в Solaris,Вы можете собрать свой пакет в Linux и посмотреть, не получите ли вы там ту же ошибку.

(Если вы переключитесь на linux, вы можете легко установить символы отладки + источник для libXm, чтобы выяснить, куда могут идти данныенеправильно.)

Для 3-й (маловероятной) возможности проверьте, что вы находитесь на последнем уровне патча.

1 голос
/ 26 февраля 2010

Это может быть длинным выстрелом, но вы пытались "разобрать" эти адреса памяти в обратном следе? Если у вас есть общее представление о сборке, вы сможете различить что-то неуместное таким образом. Как уже упоминали несколько человек, вы, вероятно, где-то обращаетесь к плохому указателю. Иногда сборка показывает, какой адрес указателя не является «правильным». Это то, что указывало мне правильное направление в прошлом.

1 голос
/ 25 февраля 2010

Я бы бросил вызовы функции memset. Все примеры, которые я видел, просто сбрасывают счетчик аргументов обратно до 0.

Я не уверен, доступен ли он вам, но DTrace был создан для такого рода вещей. Вот блог, который говорит об этом. http://blogs.oracle.com/observatory/entry/d_script_archeology

Jacob

1 голос
/ 25 февраля 2010

Вы передаете NULL в качестве первого аргумента XmCreateMainWindow(parent, ...), в то время как большинство примеров, найденных в Google, похоже, передают не-NULL Widget, исходящий от XtVaAppInitialize (), вы уверены, что не должны этого делать тоже

в противном случае в gdb установить точку останова на строке 180 win->main_window = XmCreateMainWindow(shell, win->name, args, n_args);

и выполните команду 'p * win' там, и результат должен быть просветляющим. Вероятно, элемент структуры "win", который должен быть инициализирован, является нулем или мусором, и это должно помочь вам.

1 голос
/ 25 февраля 2010

Просмотр выходных данных gdb может быть затруднен, поэтому либо используйте IDE, либо попытайтесь найти ошибку самостоятельно.

Ошибка сегментации обычно возникает:

  1. При попытке разыменования пустого указателя
  2. Изменение строкового литерала, например,
    
      char *s = "string";
      *(s+1) = 's';
    
    
      Correct way would be to allocate memory to the pointer or use Character Array or use:
    <code>
      char *s = strdup("string");
      *(s+1) = 's';
    </code>
    

  3. Попытка доступа к уже освобожденной / освобожденной памяти.
  4. Попытка изменить / получить доступ к памяти, не выделенной для программы.
1 голос
/ 25 февраля 2010

Замените memset функцией, которая устанавливает различные аргументы вручную.memset следует использовать только в байтовых массивах, потому что с любым другим типом 0 может не означать то, что вы думаете, что это значит.

1 голос
/ 20 февраля 2010

Ваша проблема в вашем memset.

Arg      args[MAX_ARGS];
...
memset(&(args), 0, sizeof(Arg)*MAX_ARGS); n_args = 0;

Здесь вы используете &(args), где вы должны использовать args или &args[0]. args - это указатель на начало массива, а &(args) - это указатель на указатель. Когда вы пытаетесь установить memset &(args), вы пытаетесь записать (потенциально) большой набор нулей в диапазоне памяти, в который вы не должны писать. В какой-то момент эта команда пыталась записать в область памяти, к которой она не должна была прикасаться, и система уничтожила ее.

1 голос
/ 19 февраля 2010

То, что я сразу вижу по просмотру вашего вывода, таково:

a) Версия используемой вами GDB устарела на год.

б) Ни один из предоставленных вами результатов не очень полезен; вам нужно опубликовать обратную трассировку.

Теперь, последняя запись в backtrace, или, точнее, где программа фактически остановилась (в данном случае libXm), почти никогда не является реальной причиной проблемы. Предполагая, что libXm не виноват, вам действительно нужна правильная обратная трассировка, чтобы увидеть последнюю точку выполнения, которая включала код, который вы написали; это более вероятный источник проблемы.

Еще одна вещь; научиться пользоваться ГБД. Это необходимо, если вы когда-нибудь собираетесь написать программу длиннее нескольких строк.

...