SIGSEGV的原因会是系统内存不足吗?
Can the cause of SIGSEGV be the low ram of the system?
我的系统内存很小,只有1.5GB。我有一个c++程序,它调用一个特定的方法大约300次。这个方法使用2个映射(它们每次都被清除),我想知道是否有可能在这个方法的一些调用中堆栈溢出并且程序失败。如果我输入小数据(因此调用该方法30次),程序运行良好。但是现在它会引发SIGSEGV错误。我试图解决这个问题大约3天,没有运气,我尝试的每一个解决方案都失败了。
我在下面找到了SIGSEGV的一些原因,但没有任何帮助什么是c++中的SIGSEGV运行时错误?
好的,下面是代码。我有2个实例,其中包含一些关键字-特征及其分数
我想要得到它们的欧几里德距离,这意味着我必须保存每个实例的所有关键字,然后找到第一个实例的关键字与第二个实例的关键字的差,然后找到第二个实例剩余部分的差。我想要的是在迭代第一个映射时,能够从第二个映射中删除元素。下面的方法被调用多次,因为我们有两个消息集合,来自第一个消息集合的每条消息都与来自第二个消息集合的每条消息进行比较。
我有这段代码,但是它突然停止了尽管我检查了它工作了几秒钟,有多个计数我在一些地方输入
注意,这是一个大学任务,所以我不能使用boost和所有这些技巧。但是我想知道如何绕过我所遇到的这个问题。
float KNNClassifier::distance(const Instance& inst1, const Instance& inst2) {
map<string,unsigned> feat1;
map<string,unsigned> feat2;
for (unsigned i=0; i<inst1.getNumberOfFeatures(); i++) {
feat1[inst1.getFeature(i)]=i;
}
for (unsigned i=0; i<inst2.getNumberOfFeatures(); i++) {
feat2[inst2.getFeature(i)]=i;
}
float dist=0;
map<string,unsigned>::iterator it;
for (it=feat1.begin(); it!=feat1.end(); it++) {
if (feat2.find(it->first)!=feat2.end()) {//if and only if it exists in inst2
dist+=pow( (double) inst1.getScore(it->second) - inst2.getScore(feat2[it->first]) , 2.0);
feat2.erase(it->first);
}
else {
dist+=pow( (double) inst1.getScore(it->second) , 2.0);
}
}
for (it=feat2.begin(); it!=feat2.end(); it++) {//for the remaining words
dist+=pow( (double) inst2.getScore(it->second) , 2.0);
}
feat1.clear(); feat2.clear(); //ka8arizoume ta map gia thn epomenh xrhsh
return sqrt(dist);
}
和我也试过这个想法,为了不删除一些东西,但它突然停止了。
float KNNClassifier::distance(const Instance& inst1, const Instance& inst2) {
map<string,unsigned> feat1;
map<string,unsigned> feat2;
map<string,bool> exists;
for (unsigned i=0; i<inst1.getNumberOfFeatures(); i++) {
feat1[inst1.getFeature(i)]=i;
}
for (unsigned i=0; i<inst2.getNumberOfFeatures(); i++) {
feat2[inst2.getFeature(i)]=i;
exists[inst2.getFeature(i)]=false;
if (feat1.find(inst2.getFeature(i))!=feat1.end()) {
exists[inst2.getFeature(i)]=true;
}
}
float dist=0;
map<string,unsigned>::iterator it;
for (it=feat1.begin(); it!=feat1.end(); it++) {
if (feat2.find(it->first)!=feat2.end()) {
dist+=pow( (double) inst1.getScore(it->second) - inst2.getScore(feat2[it->first]) , 2.0);
}
else {
dist+=pow( (double) inst1.getScore(it->second) , 2.0);
}
}
for (it=feat2.begin(); it!=feat2.end(); it++) {
if(it->second==false){//if it is true, it means the diff was done in the previous iteration
dist+=pow( (double) inst2.getScore(it->second) , 2.0);
}
}
feat1.clear(); feat2.clear(); exists.clear();
return sqrt(dist);
}
如果malloc
失败并因此返回NULL
,它确实可以导致SIGSEGV,假设程序没有正确处理该失败。然而,如果内存很低,你的系统更有可能开始杀死使用大量内存的进程(实际的逻辑更复杂,如果你感兴趣,谷歌搜索"oom killer")。
很有可能你的程序中有一个bug。找出这一点的一个好方法是使用内存调试器,如valgrind
,看看你是否访问无效的内存位置。
一个可能的解释是你的程序在释放一个动态分配的对象之后访问了它。如果对象足够小,内存分配器会为下一次分配保留内存,并且free之后的访问是无害的。如果对象很大,内存分配器将解映射用于保存该对象的页面,并且在free之后的访问将导致SIGSEGV。
几乎可以肯定的是,无论SIGSEGV发生的底层机制是什么,代码中的某个地方都存在一个bug,而这个bug是因果链的关键部分。
如上所述,最可能的原因是内存分配不当或内存泄漏。检查缓冲区是否溢出,或者在释放资源后是否试图访问资源。
1.5GB并不小。一般来说,1.5GB的内存可以做很多事情。为了让300次迭代使用1.5GB(假设操作系统内核使用0.5GB,等等),每次迭代大约需要使用32MB。这是相当多的内存,所以,我的猜测是,要么你的代码实际上是使用大量的内存,或者你的代码包含某种形式的泄漏。更有可能是后者。我曾经在小于64KB的机器上工作过,我的第一台电脑有8MB的内存,这在当时被认为是很大的。
不,如果系统内存不足,此代码无法导致段错误。Map分配使用new操作符,它不使用堆栈进行分配。它使用堆,如果内存耗尽,将抛出一个bad_alloc异常,在无效内存访问发生之前终止:
$ cat crazyalloc.cc
int main(void)
{
while(1) {
new int[100000000];
}
return 0;
}
$ ./crazyalloc
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
Aborted (core dumped)
如果另一种实现也崩溃了,这就暗示问题不在这段代码中。
问题出在Instance类上。它可能不是内存不足,它应该是缓冲区溢出,这可以通过调试器来确认。
- 是否值得降低我的代码的可读性,以便在出现内存不足错误时提供异常安全性?
- 在内存不足之前,我可以声明多少个 const 变量?
- 如何避免由于内存不足而导致 gcc 崩溃
- 检测到由于操作系统内存不足而导致子进程终止
- 导出 vulkan 内存分配句柄会导致设备内存不足
- 如何消除ROS打开CV中的内存不足错误?
- 从 C++11 代码中获取系统内存和 CPU 使用率
- 32 位应用程序内存不足
- 在本机 Android 应用中处理内存不足
- 在 Linux 上C++的无限循环中捕获内存不足的错误 bad_alloc()
- 处理静态数组内存C++的内存不足情况
- 访问违规可以是一个伪装的内存不足错误吗
- g++ 内存不足为 std::bitset 分配
- C++ 分配器在内存不足时使应用程序崩溃
- 使用队列的非递归回溯:内存不足
- C++ : 内存不足时应返回什么?
- 使用 sqlite3 时内存不足
- std::int 和 struct 内存不足的映射 (std::Bad_alloc) c++
- SQLITE 内存不足 无法执行语句
- SIGSEGV的原因会是系统内存不足吗?