例如,如果我的程序是segaults,而不是gcc打印到控制台" Segmentation Fault"我可以打印出来吗?雅顿傻瓜"?
答案 0 :(得分:1)
段错误通常是由解除引用垃圾指针引起的。因此,虽然你所问的字面答案是,正如kaylum所说,你可以在一个信号处理程序中捕获SIGSEGV,更好的答案是,在你使用指针之前,你应该问自己,“我怎么知道这个指针是有效的,我是否在我的数组的范围内?"
如果您不知道,您的程序有错误。如果你认为你这样做,你可以把假设变成一个断言,因为你的指针是有效的,它将永远通过。例如:
void fill_array( unsigned fill_this_many,
size_t array_size,
int a[array_size] )
{
assert(a);
assert( array_size >= fill_this_many );
for ( unsigned i = 0; i < fill_this_many; ++i )
a[i] = f(i);
return;
}
现在,当您要取消引用空指针或写入数组末尾时,您将收到一条详细消息,其中包含更多有用的调试信息,而且#34;某处存在段错误, &#34;它甚至可以使您免于沉默的内存损坏。
如果要编写自己的消息,可以定义一个包装器,例如:
#include <stdio.h>
#include <stdlib.h>
void fatal_error_helper( const char* file, int line, const char* restrict message )
{
fflush(stdout); // Don’t cross the streams!
fprintf( stderr, "\nError in %s, line %d: %s\n", file, line, message );
exit(EXIT_FAILURE);
}
#define fatal_error(message) fatal_error_helper( __FILE__, __LINE__, (message) )
int main(void)
{
int *big_array = calloc( 1073741824UL, sizeof(int) );
if (!big_array)
fatal_error("Not enough memory.");
return EXIT_SUCCESS;
}
一个人为的例子,说明如何在编译时进行边界检查,以便在常量发生变化时优雅地失败:
#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#define LENGTH 14U
#define M 5U
int main(void)
{
char message[LENGTH] = "hello, world!";
static_assert( M < LENGTH, "Tried to capitalize more letters than the array can hold." );
for ( unsigned i = 0; i < M; ++i )
message[i] = toupper(message[i]);
printf( "%s\n", message );
return EXIT_SUCCESS;
}
答案 1 :(得分:0)
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
void segv_handler(int sig)
{
(void)sig;
const char *msg = "Hello signal handler!";
size_t len = strlen(msg);
write(STDERR_FILENO, msg, len);
abort();
}
int main()
{
struct sigaction act;
act.sa_handler = segv_handler;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
sigaction(SIGSEGV, &act, NULL);
int *nullint = 0;
*nullint = 4;
return 0;
}
编辑:我很难解释如何做到这一点。当然,在编写信号处理程序时需要考虑很多细节。
基本限制是信号处理程序无法访问任何未被原子写入的变量/结构,因为可以在程序中的任意两条指令之间调用处理程序。这意味着没有调用堆内存管理,像printf那样缓冲等等。