当我在linux中调用operator new时出现分段错误

时间:2013-08-11 05:17:20

标签: c++ linux

在Linux Mint上,我使用operator new来分配内存:

int maxNummber = 1000000;
int* arr = new int[maxNumber];

当我运行我的代码时,我遇到了

flybird@flybird ~/cplusplus_study $ ./a.out 
-412179
Segmentation fault

当我更改maxNumber = 100时,代码成功运行。

命令free -m的结果:

flybird@flybird ~/cplusplus_study $ free -m
              total       used       free     shared    buffers     cached
Mem:          2016        800       1216          0        158        359
-/+ buffers/cache:        283       1733
Swap:         2045          0       2045

This是实际代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <iostream>
#include <fstream>
#include <ctime>
#include <memory>
#include <string.h>
#include <iterator>
#include <cstdlib>
using namespace std;

class GenRandomNumber;

class BitMap
{
public:
    BitMap(int n):maxNumer(n)
    {
        int length = 1 + n / BITSPERWORD;
        pData = new int[length];
        memset(pData, 0, length);
    }
    void set(int i)
    {
        pData[i>>SHIFT] |= 1<<(i & MASK); // i&MASK 相当于i%32
    }
    void clear(int i)
    {
        pData[i>>SHIFT] &= ~(1<<(i & MASK)); // i>>SHIFT 相当于 i/32
    }
    bool test(int i)
    {
        return pData[i>>SHIFT] & (1<<(i & MASK));
    }

    void sort(string inputFile, string outputFile)
    {
        ifstream read(inputFile.c_str());
        ofstream write(outputFile.c_str());
        int temp = 0;

        while (read>>temp)
            set(temp);

        for (int i = 0; i < maxNumer; ++i)
        {
            if(test(i))
                write<<i<<endl;
        }
        read.close();
        write.close();
    }
    ~BitMap()
    {
        delete []pData;
        pData = NULL;
    }
private:
    int* pData;
    int maxNumer;
    enum{ SHIFT = 5, MASK = 0x1F, BITSPERWORD = 32};
};

class GenRandomNumber
{
public:
    static GenRandomNumber* genInstance()
    {
        if(!mInstance.get())
            mInstance.reset(new GenRandomNumber());
        return mInstance.get();
    }

    void generate1(string fileName, int m, int maxNumber)
    {
        ofstream outFile(fileName.c_str());
        int* arr = new int[maxNumber];
        for(int i = 0; i < maxNumber; i++)
            arr[i] = i;

        int temp = 0;
        for(int j = 0; j < m; j++)
        {
            temp = randomRange(j, maxNumber - 1);
            cout<<temp<<endl;
            swap(arr[j], arr[temp]);
        }

        copy(arr, arr + m, ostream_iterator<int>(outFile, "\n"));
        delete []arr;
        outFile.close();
    }

    void generate2(string fileName, int m, int maxNumber)
    {
        BitMap bitmap(maxNumber);
        ofstream outFile(fileName.c_str());
        int count = 0;
        int temp;
        while (count < m)
        {
            srand(time(NULL));
            temp = randomRange(0, maxNumber);
            cout<<temp<<endl;
            if (!bitmap.test(temp))
            {
                bitmap.set(temp);
                outFile<<temp<<endl;
                count++;
            }
        }
        outFile.close();
    }
private:
    GenRandomNumber(){};
    GenRandomNumber(const GenRandomNumber&);
    GenRandomNumber& operator=(const GenRandomNumber&);

    int randomRange(int low, int high)
    {
        srand(clock()); // better than srand(time(NULL))
        return low + (RAND_MAX * rand() + rand()) % (high + 1 - low);;
    }

    static auto_ptr<GenRandomNumber> mInstance;
};
auto_ptr<GenRandomNumber> GenRandomNumber::mInstance;



int main()
{
    const int MAX_NUMBER = 1000000;
    GenRandomNumber *pGen = GenRandomNumber::genInstance();
    pGen->generate1("test.txt", MAX_NUMBER, MAX_NUMBER);
    BitMap bitmap(MAX_NUMBER);
    bitmap.sort("test.txt", "sort.txt");
    return 0;
}

5 个答案:

答案 0 :(得分:3)

gdb已经gave you a hint发生了错误。您使用swap的唯一地方是此功能:

void generate1(string fileName, int m, int maxNumber)
{
    ofstream outFile(fileName);
    int* arr = new int[maxNumber];
    for(int i = 0; i < maxNumber; i++)
        arr[i] = i;

    int temp = 0;
    for(int j = 0; j < m; j++)
    {
        temp = randomRange(j, maxNumber - 1);
        cout<<temp<<endl;
        swap(arr[j], arr[temp]); // <----
    }

    copy(arr, arr + m, ostream_iterator<int>(outFile, "\n"));
    delete []arr;
    outFile.close();
}

交换两个整数不太可能是罪魁祸首,除非你开始给它无效的输入。 arr[j]非常简单,应该没问题,但arr[temp]呢?此处计算temp

temp = randomRange(j, maxNumber - 1);

randomRange函数如下所示:

int randomRange(int low, int high)
{
    srand(clock()); // better than srand(time(NULL))
    return low + (RAND_MAX * rand() + rand()) % (high + 1 - low);;
}

我会说这是你的问题。 RAND_MAX * rand()可能溢出并给你很大的负数。希望很明显为什么这不好。

答案 1 :(得分:1)

1,000,000可能不应该在现代桌面上失败,所以我希望你在其他地方爆炸。

要查看问题的原因/位置:

$ gdb
gdb> file ./a.out
gdb> run
<wait for crash>
gdb> bt full

如果分配失败,您应该看到未被捕获的bad_alloc例外。

否则,请发布回溯的源代码和结果。

答案 2 :(得分:1)

问题在于您的randomRange功能。

return low + (RAND_MAX * rand() + rand()) % (high + 1 - low);;

我不知道,为什么你会(RAND_MAX + 1)多次rand()0RAND_MAX之间的返回值),但它会导致溢出并且可能是否定的。

如果C ++ 11是您的选项,我建议您使用uniform_int_distribution。它将在传递的minmax值之间返回一个数字。

#include <random>
#include <iostream>

int main()
{
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(1, 6);

    for (int n=0; n<10; ++n)
        std::cout << dis(gen) << ' ';
    std::cout << '\n';
}

答案 3 :(得分:0)

代码中有一个问题可能无法直接解释段错误,但也应引起您的注意。请注意,在类BitMap中,构造函数:

BitMap(int n):maxNumer(n)
{
    int length = 1 + n / BITSPERWORD;
    pData = new int[length];
    memset(pData, 0, length);
}

memset的第三个参数是分配数组的大小,而不是元素的数量,所以它应该是:

BitMap(int n):maxNumer(n)
{
    int length = 1 + n / BITSPERWORD;
    pData = new int[length];
    memset(pData, 0, length * sizeof(int));
}

原始代码可能会导致问题,因为memset只将部分已分配的数组初始化为零。剩下的代码可能在逻辑上是错误的,因为类BitMap在成员函数(set,clear,test)中执行二元运算符,其中所有这些都假定pData指向的数组的所有元素都设置为零。

答案 4 :(得分:0)

这是其中一个问题。 m太大,超过maxNumberarr[j]时,j=m超出其范围,因为arr的大小仅为maxNumber。请参阅堆栈帧#1上的信息:m=1606416912, maxNumber=999999

顺便说一下,一个位置很好的断言会提醒你这个问题(我是自调试代码的忠实粉丝 - 我讨厌在调试器下花时间):

void generate1(string fileName, int m, int maxNumber)
{
  assert(!fileName.empty());
  assert(m > 0 && maxNumber > 0);
  assert(m <= maxNumber);
  ...
}

后面的痕迹:

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x000000010007eef8
std::swap<int> (__a=@0x100200000, __b=@0x10007eef8) at stl_algobase.h:99
99        __a = __b;
(gdb) bt full
#0  std::swap<int> (__a=@0x100200000, __b=@0x10007eef8) at stl_algobase.h:99
    __tmp = 0
#1  0x0000000100000ff1 in GenRandomNumber::generate1 (this=0x7fff5fbffa10, fileName=@0x100200000, m=1606416912, maxNumber=999999) at t.cpp:91
    outFile = {
  <std::basic_ostream<char,std::char_traits<char> >> = {
    <std::basic_ios<char,std::char_traits<char> >> = {
      <std::ios_base> = {
        _vptr$ios_base = 0x7fff745bc350, 
        _M_precision = 6, 
        _M_width = 0, 
        _M_flags = 4098, 
        _M_exception = std::_S_goodbit, 
        _M_streambuf_state = std::_S_goodbit, 
        _M_callbacks = 0x0, 
        _M_word_zero = {
          _M_pword = 0x0, 
          _M_iword = 0
        }, 
        _M_local_word = {{
            _M_pword = 0x0, 
            _M_iword = 0
          }, {
            _M_pword = 0x0, 
            _M_iword = 0
          }, {
            _M_pword = 0x0, 
            _M_iword = 0
          }, {
            _M_pword = 0x0, 
            _M_iword = 0
          }, {
            _M_pword = 0x0, 
            _M_iword = 0
          }, {
            _M_pword = 0x0, 
            _M_iword = 0
          }, {
            _M_pword = 0x0, 
            _M_iword = 0
          }, {
            _M_pword = 0x0, 
            _M_iword = 0
          }}, 
        _M_word_size = 8, 
        _M_word = 0x7fff5fbff910, 
        _M_ios_locale = {
          _M_impl = 0x7fff745c1880
        }
      }, 
      members of std::basic_ios<char,std::char_traits<char> >: 
      _M_tie = 0x0, 
      _M_fill = 0 '\0', 
      _M_fill_init = false, 
      _M_streambuf = 0x7fff5fbff660, 
      _M_ctype = 0x7fff745c1ab0, 
      _M_num_put = 0x7fff745c1dd0, 
      _M_num_get = 0x7fff745c1dc0
    }, 
    members of std::basic_ostream<char,std::char_traits<char> >: 
    _vptr$basic_ostream = 0x7fff745bc328
  }, 
  members of std::basic_ofstream<char,std::char_traits<char> >: 
  _M_filebuf = {
    <std::basic_streambuf<char,std::char_traits<char> >> = {
      _vptr$basic_streambuf = 0x7fff745bc230, 
      _M_in_beg = 0x100803200 "", 
      _M_in_cur = 0x100803200 "", 
      _M_in_end = 0x100803200 "", 
      _M_out_beg = 0x0, 
      _M_out_cur = 0x0, 
      _M_out_end = 0x0, 
      _M_buf_locale = {
        _M_impl = 0x7fff745c1880
      }
    }, 
    members of std::basic_filebuf<char,std::char_traits<char> >: 
    _M_lock = {
      __sig = 0, 
      __opaque = '\0' <repeats 55 times>
    }, 
    _M_file = {
      _M_cfile = 0x7fff756bf0a0, 
      _M_cfile_created = true
    }, 
    _M_mode = 48, 
    _M_state_beg = {
      __mbstate8 = '\0' <repeats 127 times>, 
      _mbstateL = 0
    }, 
    _M_state_cur = {
      __mbstate8 = '\0' <repeats 127 times>, 
      _mbstateL = 0
    }, 
    _M_state_last = {
      __mbstate8 = '\0' <repeats 127 times>, 
      _mbstateL = 0
    }, 
    _M_buf = 0x100803200 "", 
    _M_buf_size = 1024, 
    _M_buf_allocated = true, 
    _M_reading = false, 
    _M_writing = false, 
    _M_pback = 0 '\0', 
    _M_pback_cur_save = 0x0, 
    _M_pback_end_save = 0x0, 
    _M_pback_init = false, 
    _M_codecvt = 0x7fff745c1cf0, 
    _M_ext_buf = 0x0, 
    _M_ext_buf_size = 0, 
    _M_ext_next = 0x0, 
    _M_ext_end = 0x0
  }
}
#2  0x0000000100000a18 in main () at t.cpp:140
    bitmap = {
  pData = 0x7fff5fc005a8, 
  maxNumer = 17
}
    pGen = (GenRandomNumber *) 0x1001000e0