2015-01-20 3 views
-1

У меня есть сервер/клиентская система, которая хорошо работает на моих машинах. Но он сбрасывает ядра на одном из компьютеров пользователей (ОС: Centos 5). Поскольку у меня нет доступа к машине пользователя, поэтому я построил двоичный код режима отладки и попросил пользователя попробовать его. Крушение произошло снова после двух дней бега. И он отправил мне основной файл дампа. Загружая файл дампа ядра с помощью gdb, он показывает местоположение сбоя, но я не понимаю причину (извините, мой предыдущий опыт в основном связан с Windows. У меня нет большого опыта работы с Linux/gdb). Я хотел бы получить ваш вклад. Благодаря!gdb - определить причину ошибки сегментации

1./вар/Журнал/сообщения на компьютере пользователя показывает Segfault:

Jan 16 9:20:39 LPZ08945 ядра: LSYSTEM [4688]: на 0000000000000000 выдаёт ошибку сегментации рип 00000000080e6433 RSP 00000000f2afd4e0 error 4

Это сообщение указывает, что существует указатель segfault в указателе инструкции 80e6433 и указатель стека f2afd4e0. Похоже, что программа пытается читать/писать по адресу 0.

2. нагрузки основной файл дампа в GDB и показывает расположение аварии:

$ GDB LSYSTEM core.19009

ГНУ GDB (GDB) CentOS (7.0.1-45.el5.centos)

... (много линий выходов из GDB опущенных)

ядро ​​был сгенерирован `./LSystem».

Программа завершена сигналом 11, Ошибка сегментации.

'# 0' 0x080e6433 в CLClient :: connectToServer (это = 0xf2afd898, Conn = 11) при liccomm/LClient.cpp: 214

214 тетсру ((символ *) & (a4.sin_addr), pHost -> h_addr, pHost-> h_length);

gdb говорит, что авария происходит на линии 214?

3. Информация о кадре. (В кадре # 0)

(GDB) Информация кадра

уровень стека 0, рамка на 0xf2afd7e0:

EIP = 0x80e6433 в CLClient :: connectToServer (liccomm/LClient.cpp: 214); сохранены EIP 0x80e6701

вызывается репера в 0xf2afd820

исходного языка C++.

список аргументов в 0xf2afd7d8, арг: это = 0xf2afd898, Conn = 11

Местные жители в 0xf2afd7d8, зр предыдущий кадр является 0xf2afd7e0

Сохраненные регистры:

EBX на 0xf2afd7cc, EBP в 0xf2afd7d8, еси в 0xf2afd7d0, ЭОД в 0xf2afd7d4, EIP в 0xf2afd7dc

кадр в f2afd7e0, почему это отличается от RSP из части 1, которая f2afd4e0? Я предполагаю, что пользователь предоставил мне несоответствующий файл дампа ядра (чей pid - 19009) и/var/log/messages file (который указывает на pid 4688).

4. Источник

(GDB) список +

209 
210   //pHost is declared as struct hostent* and 'pHost = gethostbyname(serverAddress);' 
211   memset(&a4, 0, sizeof(a4)); 
212   a4.sin_family = AF_INET; 
213   a4.sin_port = htons(nPort); 
214   memcpy((char *) & (a4.sin_addr), pHost->h_addr, pHost->h_length); 
215 
216   aalen = sizeof(a4); 
217   aa = (struct sockaddr *)&a4; 

Я не мог видеть ничего плохого в линии 214. И эта часть кода много раз должен побежал во время выполнения 2 дня.

5. Переменные

Так как GDB показано, что линия 214 был виновником. Я печатал все.

memcpy((char *) & (a4.sin_addr), pHost->h_addr, pHost->h_length); 

(GDB) печати a4.sin_addr

$ 1 = {s_addr = 0}

(GDB) печати & (a4.sin_addr)

$ 2 = (in_addr *) 0xf2afd794

(GDB) печати pHost-> h_addr_list [0]

$ 3 = 0xa24af30 "\ 202} \ 204 \ 250"

(GDB) печати pHost-> h_length

$ 4 = 4

(GDB) печать тетср

$ 5 = {} 0x2fcf90

Так что я в основном распечатаны все это на линии 214. ('pHost-> h_addr_list [0]' является 'pHost-> h_addr' из-за «#define h_addr h_addr_list [ 0] ')

Я не смог поймать что-то неправильно. Вы поймали что-нибудь подозрительное? Возможно ли, что память была повреждена в другом месте? Я ценю вашу помощь!

[редактировать] 6. назад след

(GDB) BT

'# 0' 0x080e6433 в CLClient :: connectToServer (это = 0xf2afd898, Conn = 11) при liccomm/LClient .cpp: 214

'# 1' 0x080e6701 в CLClient :: connectToLMServer (это = 0xf2afd898) в liccomm/LClient.cpp: 121

... (Frames 2 ~ 7 опущено, не имеет значения)

'# 8' 0x080937f2 в handleConnectionStarter (п = 0xf3563f98) при LManager.cpp: 166

'# 9' 0xf7f5fb41 в ??()

'# 10' 0xf3563f98 in ??()

'# 11' 0xf2aff31c in ??()

'# 12' 0x00000000 in ??()

Я следил за вложенными вызовами. Они верны.

+0

Первое, что нужно сделать, когда файл дампа ядра имеет значение «bt full», что даст вам полный стек вызовов в момент возникновения segfault. В большинстве случаев проблема кроется не в строке ошибки, а в некоторых случаях преждевременно, производя неправильные вызовы функций, которые в конечном итоге вызывают t он segfault. –

+0

Спасибо Ян! Я использовал «bt» и «bt full». Вложенные вызовы действительны. Я отредактирую вопрос и опубликую вывод из bt. –

+0

(GDB) BT # 0 0x080e6433 в CLClient :: connectToServer (это = 0xf2afd898, Conn = 11) при liccomm/LClient.cpp: 214 ... (Рамки 1 ~ 7 опущены, не имеет значения) # 8 0x080937f2 в handleConnectionStarter (par = 0xf3563f98) на LManager.cpp: 166 # 9 0xf7f5fb41 in ??() # 10 0xf3563f98 in ??() # 11 0xf2aff31c in ??() # 12 0x00000000 in ??() –

ответ

2

Проблема с memcpy заключается в том, что местоположение источника не того типа, кроме адресата.

Вы должны использовать inet_addr для преобразования адреса из строки в двоичный

a4.sin_addr = inet_addr(pHost->h_addr); 

Предыдущий код может не работать в зависимости от реализации (некоторые мое возвращение struct in_addr, другие вернутся unsigned long, но принцип тот же.

Смежные вопросы