当我在linux mint中调用操作员new时出现分段错误
Segmentation fault when I call operator new in linux mint
在Linux Mint上,我使用运算符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
这是实际的代码:
#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;
}
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();
}
交换两个int不太可能是罪魁祸首,除非你一开始就给它无效的输入。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()
可能会溢出并给你一个大负数。希望这不好的原因显而易见。
1000000可能不会在现代桌面上失败,所以我预计你会在其他地方失败。
查看问题所在:
$ gdb
gdb> file ./a.out
gdb> run
<wait for crash>
gdb> bt full
如果分配失败,您应该会看到一个未捕获的bad_alloc
异常。
否则,请发布回溯的源代码和结果。
问题出在randomRange
函数中。
return low + (RAND_MAX * rand() + rand()) % (high + 1 - low);;
我不知道,为什么你用rand()
乘以(RAND_MAX + 1)
(返回值在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';
}
这里有一个问题。CCD_ 19过大,超过了CCD_。当j=m
时,arr[j]
超出了其边界,因为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 ' ',
_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 = ' ' <repeats 55 times>
},
_M_file = {
_M_cfile = 0x7fff756bf0a0,
_M_cfile_created = true
},
_M_mode = 48,
_M_state_beg = {
__mbstate8 = ' ' <repeats 127 times>,
_mbstateL = 0
},
_M_state_cur = {
__mbstate8 = ' ' <repeats 127 times>,
_mbstateL = 0
},
_M_state_last = {
__mbstate8 = ' ' <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 ' ',
_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
代码中有一个问题可能无法直接解释段故障,但也应引起您的注意。注意,在类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指向的数组的所有元素都设置为零。
- 重载 new 和 delete 会导致 valgrind 错误
- 第一次尝试使用new动态创建结构数组,程序挂起没有错误
- 错误:'new'不能出现在常量表达式中
- 让编译器告诉哪些方法不具体,而不是错误'invalid new-expression of abstract class type'
- 使用 malloc 而不是 new 会导致 free():指针错误无效
- Valgrind 显示无效的读/写错误,但我不使用 new 或 calloc,只使用向量和固定数组
- 为什么当我尝试对使用 New 函数启动的对象调用删除函数时出现范围错误?
- `delete []`on`int*````new'''给出了malloc错误
- 在使用new和delete的情况下交叉编译错误
- CUDA错误-虚拟函数,继承,NEW运算符
- C++:光线追踪器导致内存不足错误 - 由于反复调用"new"?
- 在重载的全局new操作符中使用静态对象会导致核心转储运行时错误
- 断言错误,即使在使用 new 初始化字符指针后也是如此
- 错误 C2661:'CObject::operator new':没有重载函数需要 4 个参数
- new(std::nothrow)而不是new和错误处理
- 错误 35 错误 C2661:'operator new':没有重载函数占用 2 个参数
- 基本C++段错误,当使用new和传递指针时
- ::运算符 new 是不允许在 lambda 表达式中还是编译器错误?(更新!
- 带有内存错误访问的C++结构new
- 当我在linux mint中调用操作员new时出现分段错误