Segmentation fault linux что

Обновлено: 28.06.2024

Из командной строчки запустила программу avidemux. Хорошая программка. Раньше работала в canopus edius. Потом, по совету друзей, их же попросила поставить Linus, в обмен на лицензию эдика.

Программка маленькая, удобная. хотя, так и не поняла, как в реальном времени смотреть инзменения, которые делаю в uyv фильтре. В общем, часиков 6 позанималась с фильмом. отредактировала и поработала с фильтрами и запустила сжатие в hufuyv/pcm. Программа куда-то исчезла из поля зрения, а в консоли увидела вывод:
********** Automation ended***********

(avidemux:12920): Gtk-CRITICAL **: gtk_box_pack_end: assertion `child->parent == NULL' failed

(avidemux:12920): Gtk-CRITICAL **: gtk_box_pack_end: assertion `child->parent == NULL' failed

(avidemux:12920): Gtk-CRITICAL **: gtk_box_pack_end: assertion `child->parent == NULL' failed

(avidemux:12920): Gtk-CRITICAL **: gtk_box_pack_end: assertion `child->parent == NULL' failed

(avidemux:12920): Gtk-CRITICAL **: gtk_box_pack_end: assertion `child->parent == NULL' failed

(avidemux:12920): Gtk-CRITICAL **: gtk_box_pack_end: assertion `child->parent == NULL' failed

(avidemux:12920): Gtk-CRITICAL **: gtk_box_pack_end: assertion `child->parent == NULL' failed

(avidemux:12920): Gtk-WARNING **: Failed to set cell text from markup due to error parsing markup: Error on line 2 char 31: Element 'markup' was closed, but the currently open element is 'span'
**saving:**
Output format:0
AVI family

video process mode : 1
Process mode
mux mode : 1 mux param 0
[Bridge] Going to time 0
[Bridge] Starting with time 0, shift 0
[Bridge] Ending with time 0, sample 0
[Bridge] Going to time 0
[Bridge] Going to time 0
[PCM] Creating PCM
[PCM]Incoming :fq : 48000, channel : 2
[PCM]PCM successfully initialized
PacketQueue AVI audioQ created
[AudioQueueThread] Starting
Segmentation fault

теперь бы понять, где эта программа, ибо жалко будет потерять всю работу

мне эти ребята говорили, что бы я все в консоли запускала, что бы видеть вывод. интересная ОС :) Мне понравилась. лучше, чем глючная винда, в которой то и дело всякие напоминания о вирусах были от касперского.

I need to catch segmentation fault in third party library cleanup operations. This happens sometimes just before my program exits, and I cannot fix the real reason of this. In Windows programming I could do this with __try - __catch. Is there cross-platform or platform-specific way to do the same? I need this in Linux, gcc.

3,025 7 7 gold badges 26 26 silver badges 58 58 bronze badges 40k 38 38 gold badges 138 138 silver badges 203 203 bronze badges

5 Answers 5

On Linux we can have these as exceptions, too.

Normally, when your program performs a segmentation fault, it is sent a SIGSEGV signal. You can set up your own handler for this signal and mitigate the consequences. Of course you should really be sure that you can recover from the situation. In your case, I think, you should debug your code instead.

Back to the topic. I recently encountered a library (short manual) that transforms such signals to exceptions, so you can write code like this:

Didn't check it, though. Works on my x86-64 Gentoo box. It has a platform-specific backend (borrowed from gcc's java implementation), so it can work on many platforms. It just supports x86 and x86-64 out of the box, but you can get backends from libjava, which resides in gcc sources.

3,969 4 4 gold badges 23 23 silver badges 41 41 bronze badges 89k 15 15 gold badges 115 115 silver badges 162 162 bronze badges +1 for be sure that you can recover before catching sig segfault

Here's an example of how to do it in C.


1,265 1 1 gold badge 15 15 silver badges 35 35 bronze badges 4,438 1 1 gold badge 19 19 silver badges 15 15 bronze badges sizeof(sigaction) ==> sizeof(struct sigaction), or else you get an ISO C++ error compiling the thing. Doing IO in a signal handler is a recipe for disaster. @stefanct This is a toy example. Virtually any non-toy program is going to hold the lock on stdout at some point. With this signal handler, the worst that can probably happen is a deadlock on segfault, but that can be bad enough if you currently have no mechanism to kill rogue processes in your use case. according to 2.4.3 Signal Actions, calling printf from within a signal handler which is called as a result of an illegal indirection, whether the program is multithreaded or not is just plain undefined behavior period.

For portability, one should probably use std::signal from the standard C++ library, but there is a lot of restriction on what a signal handler can do. Unfortunately, it is not possible to catch a SIGSEGV from within a C++ program without introducing undefined behavior because the specification says:

  1. it is undefined behavior to call any library function from within the handler other than a very narrow subset of the standard library functions ( abort , exit , some atomic functions, reinstall current signal handler, memcpy , memmove , type traits, std::move , std::forward , and some more).
  2. it is undefined behavior if handler use a throw expression.
  3. it is undefined behavior if the handler returns when handling SIGFPE, SIGILL, SIGSEGV

This proves that it is impossible to catch SIGSEGV from within a program using strictly standard and portable C++. SIGSEGV is still caught by the operating system and is normally reported to the parent process when a wait family function is called.

You will probably run into the same kind of trouble using POSIX signal because there is a clause that says in 2.4.3 Signal Actions:

The behavior of a process is undefined after it returns normally from a signal-catching function for a SIGBUS, SIGFPE, SIGILL, or SIGSEGV signal that was not generated by kill() , sigqueue() , or raise() .

A word about the longjump s. Assuming we are using POSIX signals, using longjump to simulate stack unwinding won't help:

Although longjmp() is an async-signal-safe function, if it is invoked from a signal handler which interrupted a non-async-signal-safe function or equivalent (such as the processing equivalent to exit() performed after a return from the initial call to main() ), the behavior of any subsequent call to a non-async-signal-safe function or equivalent is undefined.

This means that the continuation invoked by the call to longjump cannot reliably call usually useful library function such as printf , malloc or exit or return from main without inducing undefined behavior. As such, the continuation can only do a restricted operations and may only exit through some abnormal termination mechanism.

To put things short, catching a SIGSEGV and resuming execution of the program in a portable is probably infeasible without introducing UB. Even if you are working on a Windows platform for which you have access to Structured exception handling, it is worth mentioning that MSDN suggest to never attempt to handle hardware exceptions: Hardware Exceptions.

At last but not least, whether any SIGSEGV would be raised when dereferencing a null valued pointer (or invalid valued pointer) is not a requirement from the standard. Because indirection through a null valued pointer or any invalid valued pointer is an undefined behaviour, which means the compiler assumes your code will never attempt such a thing at runtime, the compiler is free to make code transformation that would elide such undefined behavior. For example, from cppreference,

Here the true path of the if could be completely elided by the compiler as an optimization; only the else part could be kept. Said otherwise, the compiler infers foo() will never receive a null valued pointer at runtime since it would lead to an undefined behaviour. Invoking it with a null valued pointer, you may observe the value 0 printed to standard output and no crash, you may observe a crash with SIGSEG, in fact you could observe anything since no sensible requirements are imposed on programs that are not free of undefined behaviors.

What is a segmentation fault? Is it different in C and C++? How are segmentation faults and dangling pointers related?


682k 128 128 gold badges 837 837 silver badges 1207 1207 bronze badges 17.3k 15 15 gold badges 55 55 silver badges 57 57 bronze badges Typically called by attempting to dereference a null pointer, so a segmentation fault is often analogous to a Java NullPointerException .

16 Answers 16

Segmentation fault is a specific kind of error caused by accessing memory that “does not belong to you.” It’s a helper mechanism that keeps you from corrupting the memory and introducing hard-to-debug memory bugs. Whenever you get a segfault you know you are doing something wrong with memory – accessing a variable that has already been freed, writing to a read-only portion of the memory, etc. Segmentation fault is essentially the same in most languages that let you mess with memory management, there is no principal difference between segfaults in C and C++.

There are many ways to get a segfault, at least in the lower-level languages such as C(++). A common way to get a segfault is to dereference a null pointer:

Another segfault happens when you try to write to a portion of memory that was marked as read-only:

The pointer p dangles because it points to the character variable c that ceased to exist after the block ended. And when you try to dereference dangling pointer (like *p='A' ), you would probably get a segfault.

98k 41 41 gold badges 248 248 silver badges 344 344 bronze badges

It would be worth noting that segmentation fault isn't caused by directly accessing another process memory (this is what I'm hearing sometimes), as it is simply not possible. With virtual memory every process has its own virtual address space and there is no way to access another one using any value of pointer. Exception to this can be shared libraries which are same physical address space mapped to (possibly) different virtual addresses and kernel memory which is even mapped in the same way in every process (to avoid TLB flushing on syscall, I think). And things like shmat ;) - these are what I count as 'indirect' access. One can, however, check that they are usually located long way from process code and we are usually able to access them (this is why they are there, nevertheless accessing them in a improper way will produce segmentation fault).

Still, segmentation fault can occur in case of accessing our own (process) memory in improper way (for instance trying to write to non-writable space). But the most common reason for it is the access to the part of the virtual address space that is not mapped to physical one at all.

And all of this with respect to virtual memory systems.

43.9k 6 6 gold badges 36 36 silver badges 46 46 bronze badges

A segmentation fault is caused by a request for a page that the process does not have listed in its descriptor table, or an invalid request for a page that it does have listed (e.g. a write request on a read-only page).

A dangling pointer is a pointer that may or may not point to a valid page, but does point to an "unexpected" segment of memory.

720k 143 143 gold badges 1272 1272 silver badges 1304 1304 bronze badges This is true, but would it really help you if you already didn’t know what a segmentation fault is?

To be honest, as other posters have mentioned, Wikipedia has a very good article on this so have a look there. This type of error is very common and often called other things such as Access Violation or General Protection Fault.

They are no different in C, C++ or any other language that allows pointers. These kinds of errors are usually caused by pointers that are

  1. Used before being properly initialised
  2. Used after the memory they point to has been realloced or deleted.
  3. Used in an indexed array where the index is outside of the array bounds. This is generally only when you're doing pointer math on traditional arrays or c-strings, not STL / Boost based collections (in C++.)
9,743 5 5 gold badges 43 43 silver badges 59 59 bronze badges

A segmentation fault occurs when a program attempts to access a memory location that it is not allowed to access, or attempts to access a memory location in a way that is not allowed (for example, attempting to write to a read-only location, or to overwrite part of the operating system).


4,086 7 7 gold badges 38 38 silver badges 52 52 bronze badges 8,245 2 2 gold badges 34 34 silver badges 48 48 bronze badges

Segmentation fault is also caused by hardware failures, in this case the RAM memories. This is the less common cause, but if you don't find an error in your code, maybe a memtest could help you.

The solution in this case, change the RAM.


Wikipedia's Segmentation_fault page has a very nice description about it, just pointing out the causes and reasons. Have a look into the wiki for a detailed description.

In computing, a segmentation fault (often shortened to segfault) or access violation is a fault raised by hardware with memory protection, notifying an operating system (OS) about a memory access violation.

The following are some typical causes of a segmentation fault:

  • Dereferencing NULL pointers – this is special-cased by memory management hardware
  • Attempting to access a nonexistent memory address (outside process's address space)
  • Attempting to access memory the program does not have rights to (such as kernel structures in process context)
  • Attempting to write read-only memory (such as code segment)

These in turn are often caused by programming errors that result in invalid memory access:

Dereferencing or assigning to an uninitialized pointer (wild pointer, which points to a random memory address)

Dereferencing or assigning to a freed pointer (dangling pointer, which points to memory that has been freed/deallocated/deleted)

A buffer overflow.

A stack overflow.

Attempting to execute a program that does not compile correctly. (Some compilers will output an executable file despite the presence of compile-time errors.)

Сегментная адресация памяти является одним из подходов к управлению и защите памяти в операционной системе. Для большинства целей она была вытеснена страничной памятью, однако в документациях по традиции используют термин «Ошибка сегментации». Некоторые операционные системы до сих пор используют сегментацию на некоторых логических уровнях, а страничная память используется в качестве основной политики управления памятью.

Сегментная адресация памяти является одним из подходов к управлению и защите памяти в операционной системе. Для большинства целей она была вытеснена страничной памятью, однако в документациях по традиции используют термин «Ошибка сегментации». Некоторые операционные системы до сих пор используют сегментацию на некоторых логических уровнях, а страничная память используется в качестве основной политики управления памятью.

Содержание

Общие понятия

Сегментная адресация памяти — схема логической адресации памяти компьютера в архитектуре x86. Линейный адрес конкретной ячейки памяти, который в некоторых режимах работы процессора будет совпадать с физическим адресом, делится на две части: сегмент и смещение. Сегментом называется условно выделенная область адресного пространства определённого размера, а смещением — адрес ячейки памяти относительно начала сегмента. Базой сегмента называется линейный адрес (адрес относительно всего объёма памяти), который указывает на начало сегмента в адресном пространстве. В результате получается сегментный (логический) адрес, который соответствует линейному адресу база сегмента+смещение и который выставляется процессором на шину адреса.

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

Термин "сегментация" применяется в разных сферах вычислительной техники. В контексте обсуждаемой темы, термин используется с 1950 года , и относится к адресное пространству программы. Таким образом, при попытке чтения за пределами адресного пространства программы или запись на фрагмент, предназначенного только для чтения сегмента адресного пространства, приводит к ошибке сегментации, отсюда и название.

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

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

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

На уровне операционной системы эта ошибка ловится и сигнал передается в блок «offending process», где эта ошибка обрабатывается:

Причины сегментации

Наиболее распространенные причины ошибки сегментации:

  • Разыменование нулевых указателей
  • Попытка доступа к несуществующему адресу памяти (за пределами адресного пространства процесса)
  • Попытка доступа к памяти программой, которая не имеет права на эту часть памяти
  • Попытка записи в память, предназначенной только для чтения

Причины зачастую вызваны ошибками программирования, которые приводят к ошибкам связанными с памятью:

  • Создание операций с разыменованым указателем или создание неинициализированного указателя (указатель, который указывает на случайный адрес памяти)
  • Разыменование или возложение на освобожденной указатель (использование оборванного указателя, который указывает на память, которая была освобождена или перераспределена).
  • Переполнение буфера
  • Переполнение стека
  • Попытка выполнить программу, которая не компилируется правильно. (Некоторые компиляторы будут выводить исполняемый файл , несмотря на наличие ошибок во время компиляции.)

Пример Segmentation Fault

Рассмотрим пример кода на ANSI C, который приводит к ошибке сегментации вследствие присутствия квалификатора Сonst - type:

Когда программа, содержащая этот код, скомпилирована, строка «hello world» размещена в секции программы с бинарной пометкой «только для чтения». При запуске операционная система помещает её с другими строками и константами в сегмент памяти, предназначенный только для чтения. После запуска переменная s указывает на адрес строки, а попытка присвоить значение символьной константы H через переменную в памяти приводит к ошибке сегментации.

Компиляция и запуск таких программ на OpenBSD 4.0 вызывает следующую ошибку выполнения:

Вывод отладчика gdb:

В отличие от этого, gcc 4.1.1 на GNU/Linux возвращает ошибку ещё во время компиляции:

Условия, при которых происходят нарушения сегментации, и способы их проявления зависят от операционной системы. Этот пример кода создаёт нулевой указатель и пытается присвоить значение по несуществующему адресу. Это вызывает ошибки сегментации во время выполнения программы на многих системах.

Ещё один способ вызвать ошибку сегментации заключается в том, чтобы вызвать функцию main рекурсивно, что приведёт к переполнению стека:

Обычно, ошибка сегментации происходит потому что: указатель или нулевой, или указывает на произвольный участок памяти (возможно, потому что не был инициализирован), или указывает на удаленный участок памяти. Например:

Теперь разыменование любого из этих указателей может вызвать ошибку сегментации. Также, при использовании массивов, если случайно указать в качестве размера массива неинициализированную переменную. Вот пример:

Такая ошибка не прослеживается G++ при компоновке, но при запуске приложения вызовет ошибку сегментации.

Читайте также: