C++ SIGSEGV的原因可能是系统的低ram吗?

C++ SIGSEGV的原因可能是系统的低ram吗?,c++,ram,segmentation-fault,C++,Ram,Segmentation Fault,我的系统ram很小,1.5GB。我有一个C++程序,调用一个特定的方法大约300次。这个方法使用2个映射(每次都被清除),我想知道在这个方法的一些调用中是否可能堆栈溢出,程序失败。如果我放入小数据(因此该方法被调用30次),程序运行良好。但现在它引发了SIGSEGV错误。我尝试了3天来解决这个问题,但没有运气,我尝试的每个解决方案都失败了 我在下面找到了SIGSEGV的一些原因,但没有任何帮助 好的,这是代码。 我有两个实例,其中包含一些关键字特性和它们的分数 我想得到它们的欧氏距离,这意味着

我的系统ram很小,1.5GB。我有一个C++程序,调用一个特定的方法大约300次。这个方法使用2个映射(每次都被清除),我想知道在这个方法的一些调用中是否可能堆栈溢出,程序失败。如果我放入小数据(因此该方法被调用30次),程序运行良好。但现在它引发了SIGSEGV错误。我尝试了3天来解决这个问题,但没有运气,我尝试的每个解决方案都失败了

我在下面找到了SIGSEGV的一些原因,但没有任何帮助

好的,这是代码。 我有两个实例,其中包含一些关键字特性和它们的分数

我想得到它们的欧氏距离,这意味着我必须保存每个实例的所有关键字,然后找到第一个实例关键字与第二个实例关键字的差异,然后找到第二个实例剩余关键字的差异。我想要的是在迭代第一个映射时,能够从第二个映射中删除元素。下面的方法被多次调用,因为我们有两个消息集合,第一个集合中的每条消息都会与第二个集合中的每条消息进行比较

我有这个代码,但它突然停止,虽然我检查了它是几秒钟的工作与多重cout我放在一些地方

请注意,这是一项大学任务,因此我不能使用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 KNN分类器::距离(常量实例和inst1,常量实例和inst2){
地图1;
地图2;
对于(无符号i=0;等秒)-inst2.getScore(feat2[it->first]),2.0;
专长2.擦除(它->第一个);
}
否则{
dist+=pow((双)inst1.getScore(it->second),2.0;
}
}
for(it=feat2.begin();it!=feat2.end();it++){//
dist+=pow((双)inst2.getScore(it->second),2.0;
}
1.清除();2.清除()//ka8arizoume ta地图位于epomenh xrhsh
返回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);
}
float KNN分类器::距离(常量实例和inst1,常量实例和inst2){
地图1;
地图2;
地图存在;
对于(无符号i=0;等秒)-inst2.getScore(feat2[it->first]),2.0;
}
否则{
dist+=pow((双)inst1.getScore(it->second),2.0;
}
}
for(it=feat2.begin();it!=feat2.end();it++){
如果(it->second==false){//如果为true,则表示差异是在上一次迭代中完成的
dist+=pow((双)inst2.getScore(it->second),2.0;
}
}
1.清除();2.清除();存在。清除();
返回sqrt(dist);
}

如果
malloc
失败并因此返回
NULL
,则如果程序未正确处理该故障,则确实可能导致SIGSEGV。然而,如果内存如此之低,您的系统将更有可能开始终止使用大量内存的进程(实际逻辑更复杂,如果您感兴趣,请在谷歌上搜索“oom killer”)


很有可能你的程序中只存在一个bug。解决这个问题的一个好方法是使用内存调试器,例如
valgrind
,查看是否访问了无效的内存位置。

1.5GB并不是那么小。一般来说,您可以在1.5GB中完成很多工作。对于300次迭代,要使用1.5GB(比方说操作系统内核使用0.5GB等),每次迭代大约需要32MB。这是相当多的内存,所以,我猜要么你的代码实际使用了大量内存,要么你的代码包含某种泄漏。更可能是后者。我在小于64KB的机器上工作过,我的第一台电脑有8MB的ram,这在当时被认为是一个很大的问题

一种可能的解释是,您的程序在释放动态分配的对象后会访问该对象。如果对象足够小,内存分配器会保留内存以备下次分配,空闲后的访问是无害的。如果对象较大,内存分配器将取消映射用于保存对象的页面,释放后的访问将导致SIGSEGV


实际上可以肯定的是,无论SIGSEGV发生的潜在机制是什么,在因果链的关键部分的某个地方的代码中都存在错误。

否,如果系统内存不足,此代码无法导致SEGVAULT。映射分配使用新运算符,该运算符不使用堆栈进行分配。它使用堆,如果内存耗尽,将抛出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)
另一种实现也会崩溃,这一事实暗示问题不在这段代码中


问题出在实例类上。可能不是内存不足,而是缓冲区溢出,这可以通过调试器确认。

如上所述,最可能的原因是内存分配错误或内存泄漏。检查缓冲区是否溢出,或者在释放资源后是否尝试访问它。

是的,它可以(对于写得不好的程序)。如果程序试图通过malloc或new分配内存,但未检查分配是否成功,则可能会生成并使用空指针,从而导致SIGSEGV。此外,可能存在活动的
ulimit-s
,从而限制可用堆栈大小。如果您的程序使用堆栈(具有递归或大量临时变量-本地或自动),并且希望使用更多允许的堆栈,则也会生成SIGSEGV。如果您的程序在按需分页的操作系统上运行,RAM的数量与是否内存不足无关。一个1.5千兆字节的嵌入式系统听起来不太可能。即使是低内存导致了SIGSEGV,也需要程序中的一个bug才能允许它发生。错误可能是无法检查内存分配函数的返回值。但更可能的是,您有一个典型的错误,例如无法分配足够的内存