user2004672
user2004672

Reputation: 73

Error Reading Variable, Cannot Access Memory at Address X

Probably just another silly pointer issue from a C newbie. Couldn't figure this one out though. It seems that somehow my stack frame is corrupted. The assignment seems mostly irrelevant, but it's a fairly basic I/O exercises. Attempting to read in an array of structures with a single read (cannot use advanced I/O functions such as fread()).

#include "A2_Phase2.h"

void read_directory(Cdir directory[], int cnt) 
{
    int fd;
    char filename[] = "RandomStructDir.bin";

    fd = open(filename, O_RDONLY, S_IRWXU);
    if (fd < 0)
        perror(strcat(filename, " failed to open."));

    if (read(fd, &(directory[0].code[0]), sizeof(Cdir) * cnt) < 0) {
        perror(strcat(filename, " could not be accessed."));
    }

    close(fd);
}

int binary_search(Cdir directory[], char *key, int l, int r) {

    int mid = (int) r / 2;

    if (strncmp(key, directory[mid].code, 3) < 0)
        return binary_search(directory, key, l, mid - 1);
    else if (strncmp(key, directory[mid].code, 3) > 0)
        return binary_search(directory, key, mid + 1, r);
    else
        return mid;
}

int main(int argc, char *argv[]) 
{
    int COUNTRY_COUNT = atoi(argv[1]);
    printf("%d", COUNTRY_COUNT);

    Cdir *directory = (Cdir *) malloc(sizeof(Cdir) * COUNTRY_COUNT);
    read_directory(directory, COUNTRY_COUNT);
    binary_search(directory, "ZWE", 0, 238);
    free(directory);
}

I receive this error via GDB:

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400940 in binary_search (
    directory=<error reading variable: Cannot access memory at address 0x7fffff7feff8>, 
    key=<error reading variable: Cannot access memory at address 0x7fffff7feff0>, l=<error reading variable: Cannot access memory at address 0x7fffff7fefec>, 
    r=<error reading variable: Cannot access memory at address 0x7fffff7fefe8>)
    at A2_Phase2.c:19
19  int binary_search(Cdir directory[], char *key, int l, int r) { 

Thanks!

Upvotes: 3

Views: 23380

Answers (4)

Michał Leon
Michał Leon

Reputation: 2326

my stack frame is corrupted

Looks very much like you declared a variable that is too large for the stack. Instead of

int largeArray[1000][1000];

declare it as a pointer

int *largeArray[1000][1000];

Of course changes in the code are necessary.

Upvotes: 0

simonc
simonc

Reputation: 42215

int COUNTRY_COUNT = atoi(argv[1]);

reads the number of countries as an argument to the program but you later hard-code the assumption that this is >= 238 when you call

binary_search(directory, "ZWE", 0, 238);

Can you try

binary_search(directory, "ZWE", 0, COUNTRY_COUNT-1);

instead? There are also a few errors in your binary_search function which could be re-written as

int binary_search(Cdir directory[], const char *key, int l, int r)
{
    int mid = (r + l) / 2;
    int cmp = strncmp(key, directory[mid].code, 3);
    if (l >= r) {
        if (cmp == 0)
            return l;
        return -1;
    }
    if (cmp < 0) 
        return binary_search(directory, key, l, mid - 1);
    else if (cmp > 0)
        return binary_search(directory, key, mid + 1, r);
    else
        return mid;
}

The main changes are

  • calculation of mid takes account of l as well as r
  • (as noted by Kirilenko) recognise that its possible to find no match. return -1 in this case
  • reduce number of calls to strcmp. Very minor but it makes the code clearer to me and will improve performance of searches

Less importantly, there are some stylistic issues that make your code hard to read

  • Masses of unnecessary whitespace inside functions
  • Use of upper case (e.g. COUNTRY_COUNT) for variables is unusual. All upper case is often informally reserved for defines with variables using lower or camelCase

Upvotes: 6

JasonD
JasonD

Reputation: 16612

int mid = (int) r / 2;

Really? I think you'll find that's not the mid point. Also, as pointed out elsewhere, there is no termination case if the value is not found. You need to think through how the recursion will work for different inputs, including invalid ones.

I would do it something like this:

int binary_search(Cdir directory[], char *key, int l, int r)
{
    int mid = (l+r) / 2;
    int c = strncmp(key, directory[mid].code, 3);

    if(c == 0) return mid;
    if(l>=r) return -1;

    if (c < 0)
        return binary_search(directory, key, l, mid - 1);

    return binary_search(directory, key, mid + 1, r);
}

Also this:

char filename[] = "RandomStructDir.bin";

fd = open(filename, O_RDONLY, S_IRWXU);
if (fd < 0)
    perror(strcat(filename, " failed to open."));

filename[] is a fixed length array on the stack. You try to concatenate onto it when an error occurs. That could just cause a more serious error, as it's undefined behaviour - you're trashing the stack.

Upvotes: 1

md5
md5

Reputation: 23727

In your recursive function, I can't see any terminaison case if there is no matching element.

Upvotes: 0

Related Questions