Ошибка сегментирования linux mint

Не всегда программы в Linux запускаются как положено. Иногда, в силу разных причин программа вместо нормальной работы выдает ошибку. Но нам не нужна ошибка, нам нужна программа, вернее, та функция, которую она должна выполнять. Сегодня мы поговорим об одной из самых серьезных и непонятных ошибок. Это ошибка сегментации Ubuntu. Если такая ошибка происходит только один раз, то на нее можно не обращать внимания, но если это регулярное явление нужно что-то делать.

Конечно, случается эта проблема не только в Ubuntu, а во всех Linux дистрибутивах, поэтому наша инструкция будет актуальна для них тоже. Но сосредоточимся мы в основном на Ubuntu. Рассмотрим что такое ошибка сегментирования linux, почему она возникает, а также как с этим бороться и что делать.

Что такое ошибка сегментации?

Ошибка сегментации, Segmentation fault, или Segfault, или SIGSEGV в Ubuntu и других Unix подобных дистрибутивах, означает ошибку работы с памятью. Когда вы получаете эту ошибку, это значит, что срабатывает системный механизм защиты памяти, потому что программа попыталась получить доступ или записать данные в ту часть памяти, к которой у нее нет прав обращаться.

Чтобы понять почему так происходит, давайте рассмотрим как устроена работа с памятью в Linux, я попытаюсь все упростить, но приблизительно так оно и работает.

Допустим, в вашей системе есть 6 Гигабайт оперативной памяти, каждой программе нужно выделить определенную область, куда будет записана она сама, ее данные и новые данные, которые она будет создавать. Чтобы дать возможность каждой из запущенных программ использовать все шесть гигабайт памяти был придуман механизм виртуального адресного пространства. Создается виртуальное пространство очень большого размера, а из него уже выделяется по 6 Гб для каждой программы. Если интересно, это адресное пространство можно найти в файле /proc/kcore, только не вздумайте никуда его копировать.

Выделенное адресное пространство для программы называется сегментом. Как только программа попытается записать или прочитать данные не из своего сегмента, ядро отправит ей сигнал SIGSEGV и программа завершится с нашей ошибкой. Более того, каждый сегмент поделен на секции, в некоторые из них запись невозможна, другие нельзя выполнять, если программа и тут попытается сделать что-то запрещенное, мы опять получим ошибку сегментации Ubuntu.

Почему возникает ошибка сегментации?

И зачем бы это порядочной программе лезть, куда ей не положено? Да в принципе, незачем. Это происходит из-за ошибки при написании программ или несовместимых версиях библиотек и ПО. Часто эта ошибка встречается в программах на Си или C++. В этом языке программисты могут вручную работать с памятью, а язык со своей стороны не контролирует, чтобы они это делали правильно, поэтому одно неверное обращение к памяти может обрушить программу.

Почему может возникать эта ошибка при несовместимости библиотек? По той же причине — неверному обращению к памяти. Представим, что у нас есть библиотека linux (набор функций), в которой есть функция, которая выполняет определенную задачу. Для работы нашей функции нужны данные, поэтому при вызове ей нужно передать строку. Наша старая версия библиотеки ожидает, что длина строки будет до 256 символов. Но программа была обновлена формат записи поменялся, и теперь она передает библиотеке строку размером 512 символов. Если обновить программу, но оставить старую версию библиотеки, то при передаче такой строки 256 символов запишутся нормально в подготовленное место, а вот вторые 256 перезапишут данные программы, и возможно, попытаются выйти за пределы сегмента, тогда и будет ошибка сегментирования linux.

Что делать если возникла ошибка сегментирования?

Если вы думаете, что это ошибка в программе, то вам остается только отправить отчет об ошибке разработчикам. Но вы все-таки еще можете попытаться что-то сделать.

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

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

sudo apt update
sudo apt full-upgrade

Если это не помогло, нужно обнулить настройки программы до значений по умолчанию, возможно, удалить кэш. Настройки программ в Linux обычно содержатся в домашней папке, скрытых подкаталогах с именем программы. Также, настройки и кэш могут содержаться в каталогах ~/.config и ~/.cache. Просто удалите папки программы и попробуйте снова ее запустить. Если и это не помогло, вы можете попробовать полностью удалить программу, а потом снова ее установить, возможно, какие-нибудь зависимости были повреждены:

sudo apt remove пакет_программы
sudo apt autoremove
sudo apt install пакет_программы

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

Когда вы все это выполнили, скорее всего, проблема не в вашем дистрибутиве, а в самой программе. Нужно отправлять отчет разработчикам. В Ubuntu это можно сделать с помощью программы apport-bug. Обычно Ubuntu предлагает это сделать сразу, после того как программа завершилась с ошибкой сегментирования. Если же ошибка сегментирования Ubuntu встречается не в системной программе, то вам придется самим искать разработчиков и вручную описывать что произошло.

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

Рассмотрим, как его получить. Это не так уж сложно. Сначала запустите вашу программу, затем узнайте ее PID с помощью команды:

pgrep программа

Дальше запускаем отладчик gdb:

sudo gdb -q

Подключаемся к программе:

(gdb) attach ваш_pid

После подключения программа станет на паузу, продолжаем ее выполнение командой:

(gdb) continue

segfault

Затем вам осталось только вызвать ошибку:

segfault1

И набрать команду, которая выведет стек последних вызовов:

(gdb) backtrace

Вывод этой команды и нужно отправлять разработчикам. Чтобы отключиться от программы и выйти наберите:

(gdb) detach
(gdb) quit

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

Выводы

Теперь у вас есть приблизительный план действий, что нужно делать, когда появляется ошибка сегментирования сделан дамп памяти ubuntu. Если вы знаете другие способы решить эту проблему, напишите в комментариях!

Обнаружили ошибку в тексте? Сообщите мне об этом. Выделите текст с ошибкой и нажмите Ctrl+Enter.

Creative Commons License

Статья распространяется под лицензией Creative Commons ShareAlike 4.0 при копировании материала ссылка на источник обязательна .

Br3dMC писал(а): ↑

30 окт 2019, 20:02


создал пользователя — перелогинился, браузеры работают. почему?

Некорректный вопрос. Корректный: «Почему браузеры не работают от основного пользователя?» :D

Скорее всего, упираются в битый файл где-то в кэше или конфиге, или права доступа слетели.

На askubuntu народ советует удалить один файлик: rm ~/.gtkrc-2.0
Думаю, стоит начать с этого.

Кэш можно смело чистить командой sudo rm -rf ~/.cache/opera ~/.cache/google-chrome ~/.cache/chromium
Права можно восстановить командами sudo chown -R $USER:$USER /home/$USER и chmod -R 755 ~/.config/opera ~/.config/google-chrome ~/.config/chromium
(кроме папки .dbus, которая по-умолчанию принадлежит root’у. Вернём её командой sudo chown -R root:root /home/$USER/.dbus)

Если не поможет, то попробуйте удалить в папке .config (скрытая) все что связано с этими браузерами. Или переименовать/переместить в другое место, если не хотите терять историю и сохраненные пароли. Также возможно, что «собака зарыта» где-то в fontconfig или темах (окна, иконки).Если меняли — то попробуйте вернуть стандартные.

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


0

1

Привет, помогите чем можете. Linux Mint 19 Cinnamon, ядро 4.15.0-43-generic. Lib’ы i386 установил. Вообщем при запуске программы,

libpng warning: Application jmp_buf size changed
Ошибка сегментирования (стек памяти сброшен на диск)

$ file START_Linux
START_Linux: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.9, stripped

Вот что выдает gdb

Starting program: /media/eis/SO_STR_DVD/DATA/START_Linux
[Thread debugging using libthread_db enabled]
Using host libthread_db library «/lib/x86_64-linux-gnu/libthread_db.so.1».
warning: Corrupted shared library list: 0x8b15640 != 0x1
warning: Error reading shared library list entry at 0x1390
warning: Error reading shared library list entry at 0x3420
warning: Corrupted shared library list: 0x8b83420 != 0x1
libpng warning: Application jmp_buf size changed

Program received signal SIGSEGV, Segmentation fault.
0xf73469f0 in __longjmp_chk () from /lib/i386-linux-gnu/libc.so.6

Вы совершаете одну и ту же ошибку дважды.

В этом предложении объявлен указатель в глобальном пространстве имен

GeneralSlot *Slot1;

Компилятор инициализирует этот указатель нулем. Фактически это объявление эквивалентно объявлению

GeneralSlot *Slot1 = NULL;

То есть данный указатель не указывает ни на какой реальный объект типа GeneralSlot. Поэтому попытка разыменовать такой указатель в предложении

Slot1->SlotInf = NULL;

ведет к неопределенному поведению программы.

Даже если бы указатель Slot1 указывал бы на реальный объект, тем не менее вы повторяете предыдущую ошибку, инициализировав уже другой указатель Slot1->SlotInf этого объекта нулем, и пытаясь что-то записать в память по нулевому адресу

memmove(Slot1->SlotInf->slotDescription, slot_desc, 5);

Вам надо, чтобы оба указателя указывали на реальные объекты. Вы могли бы написать, к примеру,

// ...

GeneralSlot *Slot1;

int main(int argc, char* argv[])
{

    Slot1 = new GeneralSlot;

    Slot1->SlotInf = new SLOT;

    memmove(Slot1->SlotInf->slotDescription, slot_desc, 5);

    // ...

    delete Slot1->SlotInf;
    delete Slot1;

    return 0;
}

BlackStar писал(а): ↑

18.09.2007 15:19

Код программы в студию!

Спасибо!

Код — не проблема, проблема в том, что не знаю даже с чего начать. Дела обстоят так: есть shared модуль, в котором реализована функциональность загрузчика. Этот загрузчик позволяет загружать и выполнять функции из библиотек, скомпилированых под винду. Теперь: ПОД ОТЛАДЧИКОМ я с группой ребят проверяли много раз — загрузчик действительно работает и возвращает указатели на функции, которые потом реально выполняются и работают, но вот только вне отладчика все плохо.

В следующем фрагменте программа падает на вызове ф-ии SetNameInfo:

BOOL CFrameWork::LoadScanners()
{
char* path = _pwd();
strcat(path,»/SCANNERS»);

char *BASES = new char[strlen(path)+15];//, «bases.cav»);
sprintf(BASES,»%s/bases.cav»,path);
LARGE_INTEGER li;
li.HighPart=0;
li.LowPart=file_size(BASES);
if (!(m_hres = LoadModule(BASES,&li))) return false;

NAMING* naming;
DWORD naming_size;
char *names;

if (!(naming = (NAMING*)get_base(IDR_NAMING, &naming_size)) ||
!(names = (char*)get_base(IDR_MALWARE_FAMILIES)))
{
delete BASES, BASES=NULL;
return false;
}
delete BASES, BASES=NULL;
delete path, path = NULL;

path = _pwd();
strcat(path,»/SCANNERS»);
char *common = new char[strlen(path)+15];
sprintf(common,»%s/common.cav»,path);
li.HighPart=0;
li.LowPart=file_size(common);
LPVOID hmod;
if (!(hmod = LoadModule(common,&li)))
{
delete common, common = NULL;
return false;
}
delete common, common = NULL;

void (CDECL* SetNameInfo)(NAMING* , const char*, unsigned) =
(void (CDECL* )(NAMING* , const char*, unsigned ))GetProcAddr(hmod, 114);

if (!SetNameInfo)
{
UnloadModule(hmod);
return false;
}

SetNameInfo(naming, names, naming_size);
m_hcom = (LPVOID)hmod;

LoadScanners(path);
//DEBUG
//delete path, path=NULL;

return m_first != 0;
}

Сама SetNameInfo функция находится в библиотеке, которую разберает загрузчик и выглядет так:

NAMING* g_malware_types_and_names;
const char* g_malware_names;
unsigned g_malware_naming_size;

void SetNameInfo(NAMING* malware_types_and_names, const char* malware_names, unsigned malware_naming_size)
{
g_malware_types_and_names = malware_types_and_names;
g_malware_names = malware_names;
g_malware_naming_size = malware_naming_size;
}

Т. е.: она не делает ничего криминального, просто инициализирует глобальные переменные… вот на ней и валится…

Возможно, вам также будет интересно:

  • Ошибка связи терминал оплаты
  • Ошибка связи телекоммуникационного модуля lon контроллера
  • Ошибка связи со стим хои 4
  • Ошибка связи картриджа canon mf226dn
  • Ошибка связи возможно выбран неправильный продукт epson

  • Понравилась статья? Поделить с друзьями:
    0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии