1

I've been debugging for a whole day and I really am completely lost. Help! I tested tons of cases locally in Visual Studio. It works fine. But on our school's online judge system, there are several cases reporting RE(exitcode 6) which means a segment fault problem. I really don't know what happened in these cases with all random cases working perfectly locally. I checked the list of possible problem s that may cause segment fault. I just cannot work it out, so please help. IT REALLY DRIVES ME CRAZY.

Note: It's a treap. There is a lot more code in the data structure but the rest works fine so I tried to pull all relevant code. I'm sure that the treapNode* treap::deleteNode(valueType value) function trigger the segment fault problem. If you notice anything missing though, please let me know.

I am really sorry it looks so long... any advice on my coding? I would really apprieciate that!

-------------------update----------------------

ok, I'll put all my code here to make it easier for you. BTW, I don't have access to a UNIX like platform...

-------------------update inputs format----------------

an example:

5         //the total number of the following operations
0 1 2     //this operation '0' means inserting '1' and '2' seperately
0 2 3     //while this means inserting '2' in x, '3' in y;
1 2 5     //skip operation '1'
2 0 1     //this operation '2' means delete the smallest number in x, and second small number in y
0 4 1

the oj promise not to insert the number that already exists and not to delete the rank that not exists.

#include <cstdio>
#include <ctime>
#include <cstdlib>
using namespace std;

typedef unsigned long long valueType;

struct treapNode
{
    valueType value;
    int prior;
    int lChildNum;
    int rChildNum;
    treapNode* lChild;
    treapNode* rChild;
    treapNode* parent;
    treapNode(valueType value, int randPrior)
    :value(value), prior(randPrior), lChildNum(0), rChildNum(0), lChild(NULL), rChild(NULL), parent(NULL) {}
};

class treap
{
public:
    treap(valueType value);
    treapNode* searchRank(treapNode* baseNode, valueType rank);
    treapNode* insertNode(valueType value);
    void deleteRank(valueType rank);
    void printTreap(treapNode* tempRoot);
    treapNode* root;
private:
    treapNode* searchValue(valueType value);
    treapNode* lRotate(treapNode* node);
    treapNode* rRotate(treapNode* node);
};

treap::treap(valueType value)
{
    srand(time(0));
    root = new treapNode(value, rand());
}

treapNode* treap::searchRank(treapNode* baseNode, valueType rank)
{
    baseNode = root;
    int delta;
    while (1)
    {
        delta = rank-baseNode->lChildNum-1;
        if (delta==0) break;
        if (delta>0) 
        {
            baseNode=baseNode->rChild;
            rank=delta;
        }
        else baseNode=baseNode->lChild;
    }

    return baseNode;
    // int delta=rank-baseNode->lChildNum-1;
    // if (delta==0) return baseNode;
    // if (delta>0)
    // {
    //     //baseNode must have a rChild
    //     return searchRank(baseNode->rChild, delta);
    // }
    // else
    // {
    //     //baseNode must have a lChild
    //     return searchRank(baseNode->lChild, rank);
    // }
}

treapNode* treap::searchValue(valueType value)
{
    treapNode* travNode = root;
    while (1)
    {
        if (value>travNode->value)
        {
            if (travNode->rChild==NULL) break;
            travNode=travNode->rChild;
        }
        if (value<travNode->value)
        {
            if (travNode->lChild==NULL) break;
            travNode=travNode->lChild;
        }
    }

    return travNode;
}

void treap::deleteRank(valueType rank)
{
    treapNode* deleteRankPointer = searchRank(root, rank);
    treapNode* tempNodePointer=deleteRankPointer;
    while(1)
    {
        if (tempNodePointer->lChild!=NULL || tempNodePointer->rChild!=NULL)
        {
            if (tempNodePointer->lChild!=NULL && (tempNodePointer->rChild==NULL || tempNodePointer->lChild->prior>tempNodePointer->rChild->prior)) rRotate(tempNodePointer);
            else lRotate(tempNodePointer);
        }
        else
        {
            if (tempNodePointer->parent->value>tempNodePointer->value)
            {
                tempNodePointer=tempNodePointer->parent;
                tempNodePointer->lChild=NULL;
                tempNodePointer->lChildNum=0;
                deleteRankPointer->parent=NULL;
                delete deleteRankPointer;
            }
            else
            {
                tempNodePointer=tempNodePointer->parent;
                tempNodePointer->rChild=NULL;
                tempNodePointer->rChildNum=0;
                deleteRankPointer->parent=NULL;
                delete deleteRankPointer;
            }
            break;
        }
    }
    treapNode* travNode=tempNodePointer;
    while (travNode!=root)
    {
        if (travNode->parent->value>travNode->value) travNode->parent->lChildNum--;
        else travNode->parent->rChildNum--;
        travNode=travNode->parent;
    }
}

treapNode* treap::insertNode(valueType value)
{
    treapNode* tempNodePointer = searchValue(value);
    if (tempNodePointer->value>value) 
    {
        //tempNodePointer->lChildNum++;
        tempNodePointer->lChild=new treapNode(value, rand());
        tempNodePointer->lChild->parent=tempNodePointer;
        tempNodePointer=tempNodePointer->lChild;
    }
    else 
    {
        //tempNodePointer->rChildNum++;
        tempNodePointer->rChild=new treapNode(value, rand());
        tempNodePointer->rChild->parent=tempNodePointer;
        tempNodePointer=tempNodePointer->rChild;
    }
    treapNode* travNode = tempNodePointer;
    //update by prior first
    while (travNode!=root)
    {
        if (travNode->prior<=travNode->parent->prior) break;
        if (travNode->parent->value>travNode->value) rRotate(travNode->parent);
        else lRotate(travNode->parent);
    }
    //update the childNum of upper nodes
    while (travNode!=root)
    {
        if (travNode->parent->value>travNode->value) travNode->parent->lChildNum++;
        else travNode->parent->rChildNum++;
        travNode=travNode->parent;
    }

    return tempNodePointer;
}

treapNode* treap::lRotate(treapNode* node)
{
    //node has a rChild

    if (node!=root)
    {
        //node has a parent
        if (node->parent->value>node->value) node->parent->lChild=node->rChild;
        else node->parent->rChild=node->rChild;
        node->rChild->parent=node->parent;
    }
    else
    {
        root=root->rChild;
        root->parent=NULL;
        //no need to update childNum
    }
    treapNode* tempNodePointer = node->rChild;
    if (node->rChild->lChild!=NULL)
    {
        node->rChild=node->rChild->lChild;
        node->rChildNum=tempNodePointer->lChildNum;
        node->rChild->parent=node;
    }
    else 
    {
        node->rChild=NULL;
        node->rChildNum=0;
    }
    tempNodePointer->lChild=node;
    node->parent=tempNodePointer;
    tempNodePointer->lChildNum=node->lChildNum+node->rChildNum+1;

    return tempNodePointer;
}

treapNode* treap::rRotate(treapNode* node)
{
    //node has a lChild

    if (node!=root)
    {
        //node has a parent
        if (node->parent->value>node->value) node->parent->lChild=node->lChild;
        else node->parent->rChild=node->lChild;
        node->lChild->parent=node->parent;
    }
    else
    {
        root=root->lChild;
        root->parent=NULL;
        //no need to update childNum
    }
    treapNode* tempNodePointer = node->lChild;
    if (node->lChild->rChild!=NULL)
    {
        node->lChild=node->lChild->rChild;
        node->lChildNum=tempNodePointer->rChildNum;
        node->lChild->parent=node;
    }
    else 
    {
        node->lChild=NULL;
        node->lChildNum=0;
    }
    tempNodePointer->rChild=node;
    node->parent=tempNodePointer;
    tempNodePointer->rChildNum=node->lChildNum+node->rChildNum+1;

    return tempNodePointer;
}

void treap::printTreap(treapNode* tempRoot)
{
    if (tempRoot->lChild!=NULL) printTreap(tempRoot->lChild);
    printf("%lld: %d; lN: %d; rN: %d; lC: %lld; rC: %lld\n", tempRoot->value, tempRoot->prior, tempRoot->lChildNum, tempRoot->rChildNum, tempRoot->lChild==NULL?0:tempRoot->lChild->value, tempRoot->rChild==NULL?0:tempRoot->rChild->value);
    if (tempRoot->rChild!=NULL) printTreap(tempRoot->rChild);
}

int main()
{
    int n;
    scanf("%d", &n);

    int op;
    valueType inputX, inputY;
    int result=0;

    scanf("%d %lld %lld", &op, &inputX, &inputY);

    treap* xTreap=new treap(inputX);
    treap* yTreap=new treap(inputY);

    int Count=1;
    for (int i=1; i<n; i++) 
    {
        scanf("%d %lld %lld", &op, &inputX, &inputY);
        switch (op)
        {
            case 0:
                xTreap->insertNode(inputX);
                yTreap->insertNode(inputY);
                Count++;
                break;
            case 1:
                break;
            case 2:
                xTreap->deleteRank(inputX+1);
                yTreap->deleteRank(inputY+1);
                Count--;
                break;
            default:
                break;
        }
    }

    return 0;
}
laplacecrame
  • 23
  • 1
  • 4
  • Hi. You will make it easier for us, if you attach a full working example. Lots of parts are missing in your code. I experienced many times that MSVS is less sensitive to illegal memory access than gcc & unix environment. Your allocation/freeing of memory must have some fault in it. If you have access to a UNIX system, try testing/debugging there. – Palo Dec 27 '15 at 12:59
  • @Palo sorry I don have access to a UNIX like system... and I just updated my question with a full working example. Thank you for helping! – laplacecrame Dec 27 '15 at 13:11
  • What is the intended relationship between a "rank" and a value? Why are they the same type? Why do rank operations mix that type with `int`, which is a smaller type? – JSF Dec 27 '15 at 13:37
  • @JSF `deleteRank` deletes nodes by rank, and the OJ system promises to input valid rank which is less than the number of nodes at any time. – laplacecrame Dec 27 '15 at 13:38
  • Your code seems to treat rank as one based `(1..N)` but your less than comment implies zero based `(0..N-1)`. Which is it? – JSF Dec 27 '15 at 13:43
  • @JSF for example, deleteRank(2) will delete the node with the second small value of all nodes now. actually rank can be a `int`. – laplacecrame Dec 27 '15 at 13:43
  • @JSF sorry.. equal or less than, (1,N) – laplacecrame Dec 27 '15 at 13:45
  • Does the OJ also promise not to insert a value that already exists? If it did, you memory leak, corrupt the data structure and later operations seg fault. Making **your** code robust about such things is better than trusting that you understood the rules. – JSF Dec 27 '15 at 13:49
  • @JSF the OJ promise not to insert a value that already exists. – laplacecrame Dec 27 '15 at 13:54
  • @laplacecrame: maybe I do not understand your inputs right, but trying to run your code on 64-bit Linux systems with the input "50 1 20 2 32 1 2" leads to Segmentation fault. 0x000000000040092f in treap::searchRank (this=0x603070, baseNode=0x603090, rank=1) at prog.cpp:48 48 delta = rank-baseNode->lChildNum-1; (gdb) where #0 0x000000000040092f in treap::searchRank (this=0x603070, baseNode=0x603090, rank=1) at prog.cpp:48 #1 0x0000000000400a10 in treap::deleteRank (this=0x603070, rank=3) at prog.cpp:95 #2 0x000000000040118d in main () at prog.cpp:278 good luck. – Palo Dec 27 '15 at 13:57
  • @Palo, `main` seems to operate on two treaps in parallel. So your example input inserts two values into each of two treaps, then deletes the second value (item 1, zero based) from one treap and the third value from the other, which crashes because the code trusts the OJ to not delete things that aren't there. – JSF Dec 27 '15 at 14:05
  • @Palo I just updated the input format.. – laplacecrame Dec 27 '15 at 14:12
  • You don't seem to allow inserting into an empty treap. You avoided that on startup by handling the first insert during construction of the treap. But what if the second command deletes that and the third command tries to insert again? – JSF Dec 27 '15 at 14:51
  • 1
    @laplacecrame the input you specified does not crash on Linux. Do you have the possibility to submit a solution to your online evaluation system which will print out those random inputs that your app is getting that make it crash? Or is it a closed system with no debug info? :) – Palo Dec 27 '15 at 19:10
  • Raw `new` and `delete`, the standard recipe for memory problems. A large set of memory problems disappears with smart pointers such as `std::unique_ptr` (a child is _uniquely_ owned by its parent) – MSalters Dec 27 '15 at 19:47
  • @Palo I'm sorry it's a closed system :( – laplacecrame Dec 28 '15 at 01:34

0 Answers0