私はプロジェクトに取り組んでおり、最近、特に厄介なセグメンテーション違反に遭遇し始めました。ここにいくつかの背景があります:
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)
「orderadded1」は、私が追加したログです。これは、「Fetcher」クラスが「PackerManager」クラスに注文を送信するときに発生します。「PackerManager」クラスは、注文を追加する「Packer」オブジェクトを決定します。デバッグの目的で、すべての注文が1つの「Packer」オブジェクトを経由するようにコードを変更しました。
3-これは、「Packer」オブジェクトがpackItem(キューからremove()を呼び出す)を呼び出すときに、そのキューには1つのオーダーしかないことを意味します。これらのクラスの外でこれをテストしましたが、正常に動作します。
- 関連するコードは次のとおりです。
「キュー」から
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 << "\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;
}
このコードは、キューから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;
}
他に何ができるか教えてください。
編集:ここではnullポインタは問題ではないようです:これを追加してみました:
ElementType retVal;
if(front == NULL){
cout <<"oops!";
}else{
retVal = front->order;
}
コードは、retVal =front->orderの割り当てに分類されます。したがって、front!= NULLですが、front->orderはメモリの場所としては不適切であると見なされます。
編集2: わかりました、これは奇妙です。clang ++でコンパイルすると、g ++ではなく、実際に機能します(前に別の方法で述べた場合は申し訳ありません)。何?
編集3 わかりました、それで私はこれらのファイルを別のマシンにscpして、それを実行しようとしました。現在、g++とclang++の両方でセグメンテーション違反が発生していますが、キューとはまったく関係のない完全に異なる領域で発生しています。
より広範囲のメモリの問題を引き起こす可能性のある他の何かを見るべきですか?
パッカーオブジェクトの1つを更新しようとすると、セグメンテーション違反が発生するようになりました。以下のコードは、時刻の更新に失敗します(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);
}