错误类型
Segmentation fault (core dumped)
产生原因
Segmentation fault 段错误。
Core Dump 核心转储(是操作系统在进程收到某些信号而终止运行时,将此时进程地址空间的内容以及有关进程状态的其他信息写出的一个磁盘文件。这种信息往往用于调试),其实“吐核”这个词形容的很恰当,就是核心内存吐出来。
出现这种错误可能的原因(其实就是访问了内存中不应该访问的东西):
1,内存访问越界:
(1) 数组访问越界,因为下标出超出了范围。
(2) 搜索字符串的时候,通过字符串的结尾符号来判断结束,但是实际上没有这个结束符。
(3)使用strcpy, strcat, sprintf, strcmp,strcasecmp等字符串操作函数,超出了字符中定义的可以存储的最大范围。使用strncpy, strlcpy, strncat, strlcat, snprintf, strncmp, strncasecmp等函数防止读写越界。
2,多线程程序使用了线程不安全的函数。
3,多线程读写的数据未加锁保护。
对于会被多个线程同时访问的全局数据,应该注意加锁保护,否则很容易造成核心转储
4,非法指针
(1)使用NULL指针
(2)随意使用指针类型强制转换,因为在这种强制转换其实是很不安全的,因为在你不确认这个类型就应该是你转化的类型的时候,这样很容易出错,因为就会按照你强制转换的类型进行访问,这样就有可能访问到不应该访问的内存。
5,堆栈溢出
不要使用大的局部变量(因为局部变量都分配在栈上),这样容易造成堆栈溢出,破坏系统的栈和堆结构,导致出现莫名其妙的错误。
解决场景
在linux的虚拟机上跑了一个数据结构,在虚拟机上出现上述错误,在Windows的宿主机弹出错误。于是试运行一个相似的较简单的哈希函数,虚拟机上出现相同错误,,注意到以下代码:
// generates a hash value for a sting
// same as djb2 hash function
unsigned int CountMinSketch::hashstr(const char *str) {
unsigned long hash = 5381;
int c;
while (c = *str++) {
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
}
return hash;
}
这是一个针对字符串的哈希函数,其中一行
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
是问题所在,针对较长的字符串,这个hash变量会不断变大,甚至溢出。
于是尝试在这个变量每计算一次,对一个大的质数做一次取余操作,将这个值限制在一定范围内。尝试发现可以运行。
但是增加这个取余会产生额外的开销,并且对什么数取余也是需要考虑的,因为它会限制这个哈希值分布,增加碰撞的几率。但是为解决之前运行数据结构的问题提供了思路。