在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;
}
答案 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()
(0
和RAND_MAX
之间的返回值),但它会导致溢出并且可能是否定的。
如果C ++ 11是您的选项,我建议您使用uniform_int_distribution
。它将在传递的min
和max
值之间返回一个数字。
#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
太大,超过maxNumber
。 arr[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