我正在做一个项目,最近开始遇到一个特别讨厌的段错误。这里有一些背景:
1 -- 我有一个“订单”队列,我在其中测试了以下内容: a -- 填充(0 个订单、1 个订单和许多订单),删除直到 isEmpty() 返回 true,并用这些填充其他队列结果(这复制了程序的行为)
2 -- 从 gdb 中找到这个:
(gdb) run
Starting program: /Users/Nicholas M. Iodice/Dropbox/tufts/noz2/noz2/a.out
Reading symbols for shared libraries ++......................... done
order added 1
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: 13 at address: 0x0000000000000000
0x0000000100003a66 in Queue::remove (this=0x7fff5fbffaa0) at Queue.cpp:85
85 ElementType retVal = front->order;
(gdb) where
#0 0x0000000100003a66 in Queue::remove (this=0x7fff5fbffaa0) at Queue.cpp:85
#1 0x0000000100002c08 in Packer::packItem (this=0x7fff5fbffaa0, time=1) at Packer.cpp:88
#2 0x0000000100002e3f in Packer::update (this=0x7fff5fbffaa0, time=1) at Packer.cpp:131
#3 0x0000000100002e9c in PackerManager::update (this=0x7fff5fbffaa0, i=1) at Packer.cpp:295
#4 0x0000000100001ffa in Manager::run (this=0x7fff5fbff830, careAboutSupreme=false) at Manager.cpp:126
#5 0x000000010000511a in main (argc=0, argv=0x7fff5fbffb48) at main.cpp:173
(gdb)
“order added 1”是我添加的一些日志记录,它发生在我的“Fetcher”类向“PackerManager”类发送订单时,该类确定要向哪个“Packer”对象添加订单。我修改了我的代码,以便所有订单都通过一个“Packer”对象进行路由,以进行调试。
3 -- 这意味着当“Packer”对象调用packItem(它将从我的队列中调用remove()时,该队列中只有一个订单。我已经在这些类之外进行了测试,它工作正常。
- 以下是一些相关代码:
来自“队列”
Queue::Queue()
{
front = NULL;
back = NULL;
//head = NULL;
//tail = NULL;
count = 0;
}
//instert to back of queue
void Queue::insert(ElementType order)
{
if(isEmpty()){
back = new Node;
back->order = order;
back->next = NULL;
front = back;
}else{
Node* tmp = new Node;
tmp->order = order;
back->next = tmp;
back = back->next;
back->next = NULL;
}
count++;
}
//checks if head & tail = NULL
bool Queue::isEmpty()
{
if(front == NULL && back == NULL){
return true;
}
return false;
}
在这一行抛出段错误:“ElementType retVal = front->order;”
ElementType Queue::remove()
{
if(isEmpty()){
cout << "\n\tYou cannot remove from an empty Queue... Exiting.\n\n";
exit(1);
}
ElementType retVal = front->order;
//delete front;
if(front == back){
front = NULL;
back = NULL;
}else{
front = front->next;
}
count --;
return retVal;
}
此代码调用从队列中删除。它调用的是“regularOrders”
//retreives next order to begin packing
void Packer::packItem(int time)
{
if( careAboutSupreme && !supremeOrders.isEmpty() ){
orderBeingPacked = supremeOrders.remove();
orderBeingPackedStartTime = time;
}else if( careAboutSupreme && isDelayOrderWaiting ){
orderBeingPacked = orderBeingDelayed;
orderBeingPackedStartTime = orderBeingDelayedStart + delayDuration;
delayDuration = 0;
isDelayOrderWaiting = false;
}else if( !regularOrders.isEmpty() ){
orderBeingPacked = regularOrders.remove();
orderBeingPackedStartTime = time;
}
}
此外,队列通过值 i = 1 且 i > 1 的测试:
#if Q
Queue q1;
Queue q2;
for(int i=0 ; i<5 ; i++){
Order o;
q1.insert(o);
}
while(!q1.isEmpty()){
q2.insert(q1.remove());
}
sortQueueByOrderNumber(q2);
while(!q2.isEmpty()){
q2.remove();
}
cout << "Expecting to exit now" << endl;
q2.remove();
#endif
void sortQueueByOrderNumber(Queue q)
{
if(q.getCount() == 0){
return;
}
int cnt = q.getCount();
Order* orderArray = new Order[cnt];
Order tmpOrder;
//put orders into array -- after this they are in order, but in an array
while(q.getCount() != 0){
tmpOrder = q.remove();
orderArray[tmpOrder.orderNum-1] = tmpOrder;
}
//now we stuff em back into the queue, in order!
for(int i=0 ; i<cnt ; i++){
tmpOrder = orderArray[i];
q.insert(tmpOrder);
}
delete[] orderArray;
}
请让我知道我还能提供什么。
编辑:看起来空指针不是这里的问题:我尝试添加:
ElementType retVal;
if(front == NULL){
cout <<"oops!";
}else{
retVal = front->order;
}
代码仍然属于分配 retVal = front->order。所以 front != NULL 但是,它认为 front->order 是一个错误的内存位置。
编辑2: 好的,这很奇怪。使用 clang++ 编译时,它实际上可以工作(对不起,如果我之前另有说明),而不是 g++。什么?
编辑 3 好的,所以我已将这些文件 scp'd 到另一台机器并尝试运行它。现在我遇到了 g++ 和 clang++ 的分段错误,但是,在完全与队列无关的不同区域中。
还有什么我应该看的可能会导致更广泛的内存问题的东西吗?
现在尝试更新其中一个打包程序对象时会发生段错误。代码如下,它无法更新时间(this->time = time)——我认为这不应该发生,这就是为什么我认为手头可能存在更大的问题。另外,我检查了 GDB,但 this->time 不是 NULL。
void Packer::update(int time)
{
this->time = time;
//if orderNum = 0 we havent gotten a real order yet. This is the default from the constructor for Order
if(orderBeingPacked.orderNum == 0){
packItem(time);
}