C / C ++ 'da programlı olarak çekirdek döküme nasıl neden olunur?


93

C ++ uygulamamda belirli bir konumda çekirdek dökümünü zorlamak istiyorum.

Bunu şöyle bir şey yaparak yapabileceğimi biliyorum:

int * crash = NULL;
*crash = 1;

Ama daha temiz bir yol olup olmadığını bilmek isterim?

Bu arada Linux kullanıyorum.


18
Çekirdek dökümü için "daha temiz" bir yol mu? .... iyi bir;)
OJ.

5
Bu çok tatlı. Daha da iyisi bir boole (enum c?) ... if ( crash = TRUE) {/ OH SHI ... * /}
Ape-inago

3
BTW, bu yöntem tüm UNIX'lerde çalışmaz. HPUX, ilk olarak, NULL'u cezasız bir şekilde okuyup yazmanıza izin verir (neyse ki, bu yapılandırılabilir).
paxdiablo

1
Az önce 3 veya 4 harika yeni şey öğrendim. Teşekkürler.
Trevor Boyd Smith

@pax daha bir sebep şu jenerik yol bulmak için;) Teşekkür
hhafez

Yanıtlar:


78

Sinyal numarası 6'nın yükseltilmesi ( SIGABRTLinux'ta) bunu yapmanın bir yoludur (bununla birlikte, SIGABRT'nin tüm POSIX uygulamalarında 6 olması gerekmediğini unutmayın, bu nedenle SIGABRTbu, quick'n'den başka bir şeyse , değerin kendisini kullanmak isteyebilirsiniz. kirli hata ayıklama kodu).

#include <signal.h>
: : :
raise (SIGABRT);

Arayan abort()da bir çekirdek dökümü neden olur ve hatta bunu yapabilirsiniz olmadan arayarak işlem sonlandırılıyor fork()ardından abort()çocuk sadece - bakınız bu cevabı detayları için.


7
SIGABRT'nin sinyal numarası 6 olması gerekli değildir (yine de genellikle - ve özellikle Linux'ta).
Jonathan Leffler

4
Hayır, haklısın, değil ama hata ayıklama kodunun doğruluğu konusunda fazla endişelenme eğilimindeyim. Bu vahşi doğaya kaçarsa, kodumun temizliği endişelerimden en az olanı :-)
paxdiablo

2
Abort () çağrısı, bazı derleyiciler ve bazı C kitaplıkları (ARM'de gcc ve glibc veya uClibc gibi) içeren bazı mimarilerde işe yaramayabilir çünkü abort () işlevi bir noreturn özniteliğiyle bildirilir ve derleyici tüm dönüş bilgilerini tamamen optimize eder. bu da çekirdek dosyayı kullanılamaz hale getirir. Yükseltme () veya abort () çağrısının kendisini geçip izleyemezsiniz. Bu nedenle, doğrudan yükseltme (SIGABRT) veya kill (getpid (), SIGABRT) çağırmak çok daha iyidir, ki bu neredeyse aynıdır.
Alexander Amelkin

3
Maalesef, ARM'de aynı şey yükseltme (SIGABRT) ile bile olur. Yani izlenebilir bir çekirdek dosyası oluşturmanın tek yolu kill (getpid (), SIGABRT)
Alexander Amelkin 14

ulimit -c unlimitedSuvesh Pratapa cevabından gelen ipucu , bu cevap için bana çok yardımcı oldu.
Boris Däppen

75

Birkaç yıl önce Google, coredumper kitaplığını yayınladı .

Genel Bakış

Coreumper kitaplığı, çalışan programın temel dökümlerini sonlandırmadan oluşturmak için uygulamalara derlenebilir. Çekirdek çok iş parçacıklı çekirdek dosyaları yerel olarak desteklemese bile, hem tek hem de çok iş parçacıklı çekirdek dökümlerini destekler.

Coredumper, BSD Lisansı koşulları altında dağıtılmaktadır.

Misal

Bu hiçbir şekilde tam bir örnek değildir; size coredumper API'sinin neye benzediğine dair bir fikir verir.

#include <google/coredumper.h>
...
WriteCoreDump('core.myprogram');
/* Keep going, we generated a core file,
 * but we didn't crash.
 */

İstediğin bu değil, ama belki daha da iyi :)


3
Bu cevaba rastladığımda başlangıçta oldukça heyecanlandım. Ancak çekirdek damperli kamyon bugünlerde oldukça eski ve yıpranmış görünüyor. Artık çağdaş Linux çekirdeklerinde çalışmadığına dair bir işaret bile var: stackoverflow.com/questions/38314020/…
jefe2000

37

'De gösterildiği gibi sinyal man , 'çekirdek' olarak belirtilen hareket ile herhangi bir sinyal bellek dökümü zorlar. Bazı örnekler:

SIGQUIT       3       Core    Quit from keyboard
SIGILL        4       Core    Illegal Instruction
SIGABRT       6       Core    Abort signal from abort(3)
SIGFPE        8       Core    Floating point exception
SIGSEGV      11       Core    Invalid memory reference

Temel dökümleri etkinleştirdiğinizden emin olun:

ulimit -c unlimited

Teşekkürler, yardımla temel dökümleri etkinleştirme hakkındaki görüşleriniz ulimit -c unlimited.

Ulimit'i kodun içinden nasıl ayarlarsınız? @ ks1322
Karan Joisher

@KaranJoisher Bu muhtemelen kendi başına başka bir soruya değer, ancak kısacası setrlimit(RLIMIT_CORE, &core_limits);aracılığıyla ulaşılabilir kullanabilirsiniz #include <sys/resource.h>. Bir yapı türü oluşturursunuz rlimitve ardından rlim_curve rlim_maxüyelerini ayarlarsınız .
Brent Kod Yazıyor



6

Bir çekirdek dökümü oluşturmanın başka bir yolu:

$ bash
$ kill -s SIGSEGV $$

Sadece bash'ın yeni bir örneğini oluşturun ve onu belirtilen sinyalle kapatın. $$Kabuğun PID. Aksi takdirde, mevcut bashınızı öldürürsünüz ve oturumunuz kapatılır, terminal kapatılır veya bağlantısı kesilir.

$ bash 
$ kill -s SIGABRT $$
$ bash
$ kill -s SIGFPE $$

Çok basit ve kullanışlı!
firo

1
Bunu ben de beğendim. Hatta basitleştirilebilir bash -c 'kill -SIGSEGV $$'.
Christian Krause

4

Sinyal göndermek için kill (2) kullanabilirsiniz.

#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);

Yani,

kill(getpid(), SIGSEGV);

Evet. Bunu cevaba ekledim.
Eugene Yokota

2

Bazen böyle bir şey yapmak uygun olabilir:

int st = 0;
pid_t p = fork();

if (!p) {
    signal(SIGABRT, SIG_DFL);
    abort(); // having the coredump of the exact copy of the calling thread
} else {
    waitpid(p, &st, 0); // rip the zombie
}

// here the original process continues to live

Bu basit yaklaşımla ilgili bir sorun, yalnızca bir iş parçacığının ortak dökümlenmesidir.


1
 #include <stdio.h>
 #include <stdlib.h>
 int main()
 {
   printf("\n");
   printf("Process is aborting\n");
   abort();
   printf("Control not reaching here\n");
   return 0;
 }

bu yaklaşımı istediğiniz yerde kullanın :)


0
#include <assert.h>
.
.
.
     assert(!"this should not happen");

Muhtemelen NDEBUG ile karıştırılması gerekir, böylece bu özel iddia, diğer iddialar olmasa bile aktiftir.
Rhys Ulerich
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.