簡體   English   中英

使用向量時的分割錯誤

[英]Segmentation Fault when using Vectors

我正在嘗試從projecteuler.net http://projecteuler.net/problem=14解決問題

這就是問題:

為正整數的集合定義了以下迭代序列:

n→n / 2(n為偶數)n→3n +1(n為奇數)

使用上面的規則並從13開始,我們生成以下序列:

13→40→20→10→5→16→8→4→2→1可以看出,該序列(從13開始並在1結束)包含10個項。 盡管尚未證明(Collat​​z問題),但可以認為所有起始數字都以1結尾。

最長的鏈條中小於100萬的哪個起始數字?

注意:鏈條啟動后,期限就可以超過一百萬。

我首先使用了遞歸解決方案,但是經過大約100,000次迭代后,出現了分段錯誤。 因此,我提出了一個迭代解決方案,希望能夠解決該問題。 在同一點發生分段錯誤。 我查看了堆棧跟蹤,發現將值添加到向量時出現了問題,我在下面標記了這一行。 我認為向量會自動調整大小,因此我對此問題感到非常困惑。 謝謝你的幫助。 這是代碼:

#include <iostream>
#include <cstdlib>
#include <vector>
using namespace std;
 int ITERATIONS=100000;

int main()
{
vector<int> maxArray;
vector<int> newArray;
int max_size = 0;
int n = 2;
int collatz = n;
while(n <= ITERATIONS){

#Stack trace error# 
newArray.push_back(collatz);
#Stack trace error#

if(collatz == 1){
++n;
if(newArray.size() > max_size){
maxArray.clear();
for(vector<int>::const_iterator i = newArray.begin(); i < newArray.end(); ++i){
maxArray.push_back(*i);
}
max_size = newArray.size();
}
newArray.clear();
collatz = n;
}
else if(collatz%2 == 0)
collatz = collatz/2;
else
collatz = 3*collatz+1;
}
for(vector<int>::const_iterator i = maxArray.begin(); i < maxArray.end(); ++i){
cout << *i << " "; 
}
cout << "\n" << max_size;
}

堆棧跟蹤:

#0  0x00132416 in __kernel_vsyscall ()
#1  0x002641df in raise () from /lib/i386-linux-gnu/libc.so.6
#2  0x00267825 in abort () from /lib/i386-linux-gnu/libc.so.6 #3  0x001e013d in __gnu_cxx::__verbose_terminate_handler() ()  from /usr/lib/i386-linux-gnu/libstdc++.so.6
#4  0x001dded3 in ?? () from /usr/lib/i386-linux-gnu/libstdc++.so.6
#5  0x001ddf0f in std::terminate() ()  from /usr/lib/i386-linux-gnu/libstdc++.so.6
#6  0x001de05e in __cxa_throw () from /usr/lib/i386-linux-gnu/libstdc++.so.6
#7  0x001de67f in operator new(unsigned int) () from /usr/lib/i386-linux-gnu/libstdc++.so.6
#8  0x08049362 in __gnu_cxx::new_allocator<int>::allocate (this=0xbffff214, 
__n=536870912) at /usr/include/c++/4.6/ext/new_allocator.h:92
#9  0x0804923c in std::_Vector_base<int, std::allocator<int> >::_M_allocate (
this=0xbffff214, __n=536870912)   at /usr/include/c++/4.6/bits/stl_vector.h:150
#10 0x08048e7f in std::vector<int, std::allocator<int> >::_M_insert_aux (
this=0xbffff214, __position=..., __x=@0xbffff220: -91)
at /usr/include/c++/4.6/bits/vector.tcc:327
#11 0x08048bdd in std::vector<int, std::allocator<int> >::push_back (
this=0xbffff214, __x=@0xbffff220: -91)
at /usr/include/c++/4.6/bits/stl_vector.h:834
#12 0x08048897 in main () at iterativeCollatz.cpp:16

條件i < newArray.end()應該是i != newArray.end() 當然,這也適用於i < maxArray.end()

#6  0x001de05e in __cxa_throw () from /usr/lib/i386-linux-gnu/libstdc++.so.6

__cxa_throw調用表明正在拋出C ++異常。

#5  0x001ddf0f in std::terminate() ()  from /usr/lib/i386-linux-gnu/libstdc++.so.6

std::terminate函數立即退出應用程序。 這可能是由於以下幾個原因:

  1. 在對象的析構函數中引發異常,而在引發另一個異常時。
  2. 該程序沒有try ... catch處理程序。

在這種情況下,選項2最有可能。 運行該程序應導致類似以下內容:

terminate called after throwing an instance of 'std::bad_alloc'
  what():  std::bad_alloc

Program received signal SIGABRT, Aborted.

這給你的例外(的消息what輸出)。

#7  0x001de67f in operator new(unsigned int) () from /usr/lib/i386-linux-gnu/libstdc++.so.6

此行表示分配內存時觸發了異常(最有可能是std::bad_alloc ,指示內存不足)。

因此,我將檢查您是否沒有分配內存不足的大向量。

注意:您可以通過編寫類似以下內容來添加自己的try...catch處理程序:

try
{
    // Your code here.
}
catch (const std::exception &e)
{
    std::cout << "Error: " << e.what() << std::endl;
}

每當vector實現不再有空間時, vector實現都會增加它們的大小。 這通常是通過將空間加倍(2、4、8、16,...)來完成的。 這將很快變得非常大,並且您擁有2個向量,可容納100000個元素。 還要注意,在增加向量時,它需要保留舊數據以將其復制到新向量中。

您可以在maxArraynewArray上使用reserve方法在循環之前設置所需的大小。 那是:

maxArray.reserve(ITERATIONS);
newArray.reserve(ITERATIONS);

由於向量不必增加內部數據數組來添加新元素,因此這也將確保更干凈的性能。

我們進行以下觀察:

  1. 最小的單個鏈僅由數字1組成。其長度為1。
  2. 長鏈只能通過將 x放在以x/2 (如果x為偶數)或3x+1 (如果x為奇數)開頭的鏈上而形成。 長鏈的長度為1加上尾巴的長度。
  3. 連鎖店開始運作后,期限就可以超過一百萬。
  4. 解決這個問題實際上並不需要負數。
  5. 沒有鏈長為0。

我們得出以下結論:

  1. 從觀察1和2:一旦找到從x開始的鏈長,就必須記住它。 這避免了重新計算尾巴的長度。 此外,我們可以將鏈長度解釋為0 (這是默認構造std::size ),因為“此長度尚未計算”。
  2. 從觀察值3:對於任何x > 1000000 ,如果最終需要計算從x開始的鏈的長度,則不能保證我們會對從y開始的每個鏈的長度感興趣,以使x > y >= 1000000 因此,我們應該使用關聯的數據結構(例如std::map ),而不是std::vector來存儲記錄的長度:
  3. 從觀察值3和4:我們將使用盡可能大的無符號整數類型。 在不使用bignum庫(例如GMP)的情況下,我們想要的類型是std::uint64_t
  4. 從觀察5:我們可以使用鏈長值為0來表示“此鏈長尚未計算”。 這特別方便,因為C ++的關聯容器在將operator []與容器中不存在的鍵一起使用時默認構造一個值,並且將整數類型的默認構造值初始化為0。

為了方便起見,使用C ++ 11構造編寫的結果程序是這樣的:

#include <iostream>
#include <map>
#include <set>
#include <stack>

int main()
{
  typedef std::uint64_t num;

  // ys[x] is the length of the chain starting at x.
  // xms is the set of numbers that yield the longest chains.
  // ym is the length of the longest chain so far.
  std::map<num, num> ys = {{1,1}};
  std::set<num> xms = {1};
  num ym = 1;

  for (num i = 2; i < 1000000; ++i)
  {
    std::stack<num> xs;
    num x = i, y = ys[x];

    // Compute successive chain elements until
    // a base element is reached whose chain
    // length has already been memoized.
    while (!y)
    {
      xs.push(x);
      x = (x & 1) ? (3*x + 1) : (x/2);
      y = ys[x];
    }

    // The lengths of the newly computed elements
    // can be found by repeatedly incrementing
    // the base element's chain length.
    while (!xs.empty())
    {
      x = xs.top();
      ys[x] = ++y;
      xs.pop();
    }

    // Keep track of which number(s)
    // yield the longest chain(s).
    if (y >= ym)
    {
      if (y > ym)
      {
        xms.clear();
        ym = y;
      }
      xms.insert(x);
    }
  }

  for (num xm : xms)
    std::cout << xm << ' ';

  return 0;
}

我已經測試了您的代碼,但是沒有SIGSEGV,也許您應該提供更多信息。

這是我的建議:

向量類有一個名為capacity()的成員函數,也許您應該檢查一下。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM