c++通过GDB接收段错误,而不是xCode——需要帮助调试
c++ receives segfault through GDB but not xCode -- need help debugging
我正在做一个项目,最近开始遇到一个特别严重的段错误。下面是一些背景信息:
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)
"订单添加1"是我添加的一些日志记录,当我的"Fetcher"类向"PackerManager"类发送订单时发生,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;
}
抛出这行segfault: "ElementType retVal = front->order;"
ElementType Queue::remove()
{
if(isEmpty()){
cout << "ntYou cannot remove from an empty Queue... Exiting.nn";
exit(1);
}
ElementType retVal = front->order;
//delete front;
if(front == back){
front = NULL;
back = NULL;
}else{
front = front->next;
}
count --;
return retVal;
}
这段代码从队列中调用remove。它调用的是"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->顺序。所以front != NULL,然而,它认为front->顺序是一个不好的内存位置。
编辑2:好吧,这很奇怪。当使用clang++编译时,它实际上可以工作(如果我之前另有说明,请原谅),只是不是g++。怎么啦?
编辑3 好了,我把这些文件scp到另一台机器上并试着运行它。现在我在g++和clang++中都遇到了分段错误,但是,在与队列完全无关的完全不同的区域。
是否有其他东西我应该看看,可能会导致更广泛的内存问题?
段错误现在发生时,试图更新一个包装器对象。代码如下,它无法更新时间(this->time = time)——我认为这不应该发生,这就是为什么我认为可能有一个更大的问题。另外,我检查了GDB,但这个->时间不是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);
}
isEmpty()
返回false 不保证front
不是NULL
Put assert in isEmpty()
like:
bool Queue::isEmpty()
{
if(front == NULL || back == NULL){
assert(front == NULL);
assert(back == NULL);
return true;
}
return false;
}
同样,你是否在构造函数中将front
和back
初始化为NULL
?
编辑:
另一件要检查的事情是你的订单号是否超过sortQueueByOrderNumber
:
void sortQueueByOrderNumber(Queue q)
{
...
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();
assert(tmpOrder.orderNum >= 1); // <<<<<<<<<<<<<<<<<<<<<
assert(tmpOrder.orderNum-1 < cnt); // <<<<<<<<<<<<<<<<<<<<<
orderArray[tmpOrder.orderNum-1] = tmpOrder;
}
...
}
EDIT2:另一个潜在的缺陷:确保在复制队列结构时实现赋值操作符和复制构造函数:
Queue::Queue(const Queue &other) :
front(NULL),
back(NULL),
count(0)
{
Node *node = other.front;
while (node != NULL)
{
insert(node->order);
node = node->next;
}
}
否则,例如,当调用sortQueueByOrderNumber(Queue q)
时(假设您没有使其成为Maciek B指出的引用),您将共享(因为等待默认复制构造函数工作)多个queue实例之间的队列节点,或者更糟的是,您将在一个对象上的所有节点上调用delete超出范围(例如在sortQueueByOrderNumber
的末尾),而另一个Queue
实例仍然指向(删除)Node
对象。
删除注释掉了吗?
ElementType retVal = front->order;
//delete front;
if(front == back){
front = NULL;
back = NULL;
}else{
front = front->next;
}
你不应该删除front
,然后使用front->next
。试试这个:
ElementType retVal = front->order;
Node* x = front;
if(front == back){
front = NULL;
back = NULL;
}else{
front = front->next;
}
delete x;
编辑:方法sortQueueByOrderNumber
按值接受Queue
参数,因此front
和back
的任何更改都不会存储在原始Queue
对象中。将签名更改为:
void sortQueueByOrderNumber(Queue& q)
如果你仍然有问题,那么使用valgrind
。它应该找到这些内存问题,或者至少为您指明正确的方向。
- 每当调试C (Xcode 10.1)时,输入问题
- Xcode 7调试器不会中断内联标头函数
- XCode 附加进程/分离进程(以编程方式分离调试器)
- 调试Xcode 4.4中的libc++问题
- 在Xcode中,介绍如何使用具有源代码的外部库进行调试
- Xcode调试器找不到我的文件
- XCode调试器lldb中断,没有错误输出,但程序运行良好
- 在Xcode中调试一个没有调试符号的dylib
- Xcode调试器未显示C++cout输出
- Xcode 5 带有 %s 格式说明符的 LLVM printf 在调试控制台中不起作用
- 如何使用 XCode 6.1 C++调试模式检查所有局部变量
- Xcode 调试不显示 for- 或 while-loops
- 如何让Xcode链接并使用Boost文件系统调试应用程序
- 删除Xcode 5.1项目中的所有调试表达式
- Xcode 4外部构建项目和调试
- 打印/调试libc++ STL与Xcode/LLDB
- 使用Xcode调试c++ .cpp文件
- 如何避免XCode调试器步进std系统头文件
- xcode链接器在调试模式下错误(重复符号)
- 有没有一种方法可以从Xcode调试器的调用堆栈中删除内联函数