Повреждение кучи в HP-UX? - PullRequest
2 голосов
/ 06 марта 2009

Я пытаюсь понять, что происходит с программой, запущенной в HP-UX 11.11, которая приводит к SIGSEGV (11, ошибка сегментации):

(gdb) bt
#0  0x737390e8 in _sigfillset+0x618 () from /usr/lib/libc.2
#1  0x73736a8c in _sscanf+0x55c () from /usr/lib/libc.2
#2  0x7373c23c in malloc+0x18c () from /usr/lib/libc.2
#3  0x7379e3f8 in _findbuf+0x138 () from /usr/lib/libc.2
#4  0x7379c9f4 in _filbuf+0x34 () from /usr/lib/libc.2
#5  0x7379c604 in __fgets_unlocked+0x84 () from /usr/lib/libc.2
#6  0x7379c7fc in fgets+0xbc () from /usr/lib/libc.2
#7  0x7378ecec in __nsw_getoneconfig+0xf4 () from /usr/lib/libc.2
#8  0x7378f8b8 in __nsw_getconfig+0x150 () from /usr/lib/libc.2
#9  0x737903a8 in __thread_cond_init_default+0x100 () from /usr/lib/libc.2
#10 0x737909a0 in nss_search+0x80 () from /usr/lib/libc.2
#11 0x736e7320 in __gethostbyname_r+0x140 () from /usr/lib/libc.2
#12 0x736e74bc in gethostbyname+0x94 () from /usr/lib/libc.2
#13 0x11780 in dnetResolveName (name=0x400080d8 "smtp.org.com", hent=0x737f3334) at src/dnet.c:64
..

Проблема, кажется, возникает где-то внутри libc! Трассировка системного вызова заканчивается на:

Connecting to server smtp.org.com on port 25
write(1, "C o n n e c t i n g   t o   s e ".., 51) .......................... = 51
open("/etc/nsswitch.conf", O_RDONLY, 0666) ............................... [entry]
open("/etc/nsswitch.conf", O_RDONLY, 0666) ................................... = 5
  Received signal 11, SIGSEGV, in user mode, [SIG_DFL], partial siginfo
    Siginfo: si_code: I_NONEXIST, faulting address: 0x400118fc, si_errno: 0
    PC: 0xc01980eb, instruction: 0x0d3f1280
exit(11) [implicit] ............................ WIFSIGNALED(SIGSEGV)|WCOREDUMP

Последняя инструкция программы:

struct hostent *him;
him = gethostbyname(name); // name == "smtp.org.com" as shown by gdb

Это проблема с системой, или я что-то упустил? Любое руководство для копания глубже будет оценено.

Thx.

Ответы [ 4 ]

1 голос
/ 10 марта 2009

Короче говоря: vsnprintf повредил мою кучу под HP-UX 11.11. vsnprintf был введен в C99 (ISO / IEC 9899: 1999) и «эквивалентен snprintf со списком переменных аргументов» (§7.19.6.12.2), snprintf (§7.19.6.5.2): «Если n равно нулю , ничего не написано ". Что ж, HP UX 11.11 не соответствует этой спецификации. Когда 2-й аргумент == 0, аргументы записываются в конце 1-го аргумента .. что, конечно, портит кучу (я не выделяю пробел при maxsize == 0, учитывая, что ничего не должно быть записано ).

HP справочные страницы неясны («Ответственность за доступность хранилища лежит на пользователе»), ничего не сказано о случае maxsize == 0 . Хорошая ловушка .. по крайней мере, раздел ПРЕДУПРЕЖДЕНИЙ на странице руководства должен предупреждать пользователей, совместимых со стандартом std ..

Это яйцо / курица pb: vnsprintf является вариативным, поэтому для «ответственности пользователя» за обеспечение достаточного объема памяти «ответственность пользователя» должна сначала знать, сколько места необходимо. И лучший способ сделать это это вызвать vnsprintf со вторым аргументом == 0: тогда он должен вернуть количество требуемого пространства и ничего не sprintfs .. ну, кроме HP! Одно из решений использовать vnsprintf при этом нарушении std для определения необходимого пространства: malloc на 1 байт больше в ваш буфер (1-й аргумент) и вызов vnsprintf (buf + buf.length, 1, ..). Это только помещает \ 0 в новый байт, который вы выделили. Глупо, но эффективно. Если вы находитесь в условиях wchar, malloc (sizeof ..).

В любом случае, обходной путь тривиален: никогда не вызывайте v / snprintf в HP-UX с maxsize == 0! У меня теперь счастливая стабильная программа!

Спасибо всем, кто внес свой вклад.


Повреждение кучи через vsnprintf под HP-UX B11.11 Эта программа печатает "@@" под Linux / Cygwin / .. Он печатает "@ fooo @" под HP-UX B11.11:

#include <stdarg.h>
#include <stdio.h>

const int S=2;

void f (const char *fmt, ...) {
        va_list ap;
        int actualLen=0;
        char buf[S];

        bzero(buf, S);

        va_start(ap, fmt);
        actualLen = vsnprintf(buf, 0, fmt, ap);
        va_end(ap);

        printf("@%s@\n", buf);
}

int main () {
        f("%s", "fooo");
        return 0;
}
1 голос
/ 07 марта 2009

Ваша трассировка стека находится в malloc, что почти наверняка означает, что где-то вы повредили одну из malloc структур данных. Как сказал предыдущий ответ , вы, вероятно, переполнены или переполнены буфера и повреждены один из элементов, выделенных из кучи.

Другое объяснение состоит в том, что вы пытались сделать free для чего-то, что не пришло из кучи, но это менее вероятно - это могло бы произойти сбой прямо в free.

1 голос
/ 06 марта 2009

Всякий раз, когда такая ситуация случается со мной (неожиданный сбой в системной библиотеке), обычно это происходит потому, что я делал что-то глупое где-то еще, то есть переполнение буфера, двойное удаление указателя и т. Д.

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

valgrind -v --leak-check = да --show-достижимо = да ./myprog

Я предполагаю, что valgrind может использоваться в HP-UX ...

0 голосов
/ 06 марта 2009

Чтение справочной страницы (OS X) говорит о том, что gethostbyname() возвращает указатель, но, насколько я могу судить, может не выделять память для этого указателя. Вам сначала нужно malloc()? Попробуйте это:

struct hostent *him = malloc(sizeof(struct hostent));
him = gethostbyname(name);
...
free(him);

Это работает лучше?

РЕДАКТИРОВАТЬ: Я проверил это, и это, вероятно, неправильно. Конечно, я использовал пустую строку «stmp.org.com» вместо переменной, но обе версии (с malloc() и без) работали на OS X. Возможно, HP-UX отличается.

...