C++ pointer "losing" its value

-2

As an exercise (largely an exercise in trying to write something using pointers), I'm writing a cache simulation, specifically of the pseudo least recently used system from the old 486. I'm getting an "Access violation reading location" error on the line:

int min = treeArray[set]->root->findPLRU();

Initially the treeArray seems to be initialised properly (if I pause the program at the start and take a look, it's all as should be), but when the programme breaks and I delve in to examine things the root of the tree in question isn't defined.

I feel it's quite probable that I'm making some sort of very elementary pointer mistake, which is causing the pointer to the node to be "lost" somewhere, but I've no clue what it might be. Is there something in particular I need to do to "hold on" to a pointer value?

#include "stdafx.h"
#include "stdlib.h"
#include <conio.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <io.h>

#include "main.h"

//char fn[80];                              // trace filename
int tf;                                     // trace file
trace buf[BUFSZ / sizeof(trace)];           // buffer SIZE
int LRUHits = 0;
int pLRUHits = 0;
int randomHits = 0;
int height;

int cachelinenumber;



//log2 helper function
int log2(int n)
{
int i = 0;
while (n)
{
    n = n >> 1;
    i++;
}
return i - 1;
}

class CacheLine{
public:
int tag;
int access;
CacheLine();
};

class Cache;

class Node{
public:
bool goRight;
Node* left;
Node* right;
int leftCacheLine;
int rightCacheLine;

Node(int depth) // constructor
{
    goRight = false;
    if (depth < height - 1)
    {
        left = new Node(depth + 1);
        right = new Node(depth + 1);
        leftCacheLine = -1;
        rightCacheLine = -1;
    }
    else
    {
        leftCacheLine = cachelinenumber;
        cachelinenumber++;
        rightCacheLine = cachelinenumber;
        cachelinenumber++;
    }
    //printf("Depth: %d, Height: %d, Left: %d, Right: %d\n", depth, height, leftCacheLine, rightCacheLine);
}

~Node()
{
    delete left;
    delete right;
}

int findPLRU()
{
    if (leftCacheLine < 0 || rightCacheLine < 0)
    {
        if (goRight)
        {
            goRight = false;
            return right->findPLRU();
        }
        else
        {
            goRight = true;
            return left->findPLRU();
        }
    }
    else
    {
        if (goRight)
        {
            goRight = false;
            return rightCacheLine;
        }
        else
        {
            goRight = true;
            return leftCacheLine;
        }
    }
}
};

class Tree{
public:
Node* root;
Tree()
{
    root = new Node(0);
}

~Tree()
{
    delete root;
}

};

//cache class
class Cache
{
public:
CacheLine *cache;

int l, k, n, replacementPolicy;
int log2l, log2n;
int access;
Tree** treeArray;
//constructor
Cache(int ll, int kk, int nn, int _replacementPolicy)
{
    l = ll;
    k = kk;
    n = nn;
    replacementPolicy = _replacementPolicy;
    log2l = log2(l);
    log2n = log2(n);

    cache = (CacheLine*)malloc(sizeof(CacheLine)*k*n);

    for (int i = 0; i < k*n; i++)
    {
        cache[i].tag = 0x80000000;
        cache[i].access = 0;
    }

    if (replacementPolicy == 1)
    {
        cachelinenumber = 0;
        treeArray = new Tree*[n];
        for (int i = 0; i < n; i++)
        {
            treeArray[i] = new Tree();
        }
    }
    access = -1;
}

//destructor
~Cache()
{
    free(cache);
}



//test for hit
void hit(int a) 
{
    access++;

    int set = (a >> log2l) & (n - 1);
    int tag = a >> (log2n + log2l);

    CacheLine* c = &cache[set*k];

    for (int i = 0; i < k; i++)
    {
        if (c[i].tag == tag)
        {
            c[i].access = access;
            if (replacementPolicy == 0)
                LRUHits++;
            else if (replacementPolicy == 1)
                pLRUHits++;
            else if (replacementPolicy == 2)
                randomHits++;
            break;
        }
    }

    if (replacementPolicy == 0) //LRU
    {
        int min = 0; 
        int minv = c[0].access;
        for (int i = 1; i < k; i++)
        {
            if (c[i].access < minv)
            {
                minv = c[i].access;
                min = i;
            }
        }
        c[min].tag = tag;
        c[min].access = access;
    }
    else if(replacementPolicy == 1) // pseudoLRU
    {
        int min = treeArray[set]->root->findPLRU();
        c[min].tag = tag;
        c[min].access = access;
    }
    else // random
    {
        srand(clock());
        int randomNumber = rand()%k;
        c[randomNumber].tag = tag;
        c[randomNumber].access = access;
    }
    return;
}
};

void analyse (int l, int k, int n)
{
height = log2(k) + 1;
char fn[] = "ico0.trace";
if ((tf = open(fn, _O_RDONLY | _O_BINARY )) == -1) {
    printf("unable to open file %s\n", fn);
    exit(0);
}

LRUHits = 0;
pLRUHits = 0;
randomHits = 0;
Cache *cache0 = new Cache(l, k, n, 0); // LRU
Cache *cache1 = new Cache(l, k, n, 1); // pseudoLRU
Cache *cache2 = new Cache(l, k, n, 2); // random

int bytes, word0, a, type, burstcount;
int hits = 0;
int tcount = 0;

while (bytes = read(tf, buf, sizeof(buf)))
{
    for (int i = 0; i <  bytes / (int) sizeof(trace); i++, tcount++) 
    {
        word0 = buf[i].word0;
        a = (word0 & ADDRESSMASK) << 2;
        type = (word0 >> TYPESHIFT) & TYPEMASK;
        burstcount = ((word0 >> BURSTSHIFT) & BURSTMASK) + 1;
        cache0->hit(a);
        cache1->hit(a);
        cache2->hit(a);
    }
}
printf("Hits: %d  Total: %d\n", LRUHits, tcount);
printf("Hits: %d  Total: %d\n", pLRUHits, tcount);
printf("Hits: %d  Total: %d\n\n\n", randomHits, tcount);
delete cache0;
delete cache1;
delete cache2;
}


int _tmain(int argc, _TCHAR* argv[])
{
//analyse(16, 1, 8);
analyse(16, 2, 512);
//analyse(16, 4, 256);
//analyse(16, 8, 128);
//analyse(16, 1024, 1);
_getch();
return 0;
}
c++
pointers
asked on Stack Overflow Apr 10, 2012 by Diarmuid Ó Muirgheasa • edited Apr 3, 2020 by halfer

1 Answer

6

Your question hasn't yet been pounced upon, probably because your code still doesn't compile since you've not provided main.h.

And even then it would annoy most folks trying to help you because you make no mention of the ico0.trace file that is required to prevent the code from immediately exiting.

You say int min = treeArray[set]->root->findPLRU(); access violates.

1) the value of set can never exceed the size n of your treeArray since you & n-1 the range of input values.

2) since your ~Tree() destructor is never called there will always be a treeArray[set]->root

3) since you *always create new left & right nodes whenever leftCacheLine = -1 or rightCacheLine = -1 it cannot be due to recursive findPLRUs

So, the pointer to the node is not being "lost" somewhere; it is being stomped on.

Try replacing:

    int min = treeArray[set]->root->findPLRU();
    c[min].tag = tag;
    c[min].access = access;

with:

    int min = treeArray[set]->root->findPLRU();
    if (min >= k*n)
    {
        printf("ook\n");
    }
    else
    {
        c[min].tag = tag;
        c[min].access = access;
    }

and I think you will discover what's doing the stomping. ;)

answered on Stack Overflow Apr 10, 2012 by violet313 • edited Apr 3, 2020 by halfer

User contributions licensed under CC BY-SA 3.0