读取变量时出错,无法访问地址X处的内存

时间:2013-01-23 16:37:11

标签: c

可能只是来自C新手的另一个愚蠢的指针问题。虽然无法想象这一点。似乎我的堆栈框架已被破坏。该任务似乎大多无关紧要,但它是一个相当基本的I / O练习。尝试使用单个读取读取结构数组(不能使用高级I / O函数,如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);
}

我通过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) { 

谢谢!

4 个答案:

答案 0 :(得分:4)

int COUNTRY_COUNT = atoi(argv[1]);

读取国家/地区的数量作为该计划的参数,但您稍后会在调用

时将此假设硬编码为>= 238
binary_search(directory, "ZWE", 0, 238);

你能试试吗

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

代替?您的binary_search函数中也存在一些错误,可以重写为

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;
}

主要变化是

  • mid的计算考虑了l以及r
  • (如Kirilenko所述)认识到可能找不到匹配。在这种情况下返回-1
  • 减少对strcmp的通话次数。非常轻微,但它使代码更清晰,并将提高搜索性能

不太重要的是,有一些风格问题使您的代码难以阅读

  • 在函数内部有大量不必要的空格
  • 对变量使用大写(例如COUNTRY_COUNT)是不常见的。所有大写字母通常都是非正式保留的,用于使用lower或camelCase
  • 的变量定义

答案 1 :(得分:1)

int mid = (int) r / 2;

真的?我想你会发现这不是中点。此外,正如其他地方所指出的,如果找不到该值,则没有终止案例。您需要考虑递归如何适用于不同的输入,包括无效的输入。

我会这样做:

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);
}

还有:

char filename[] = "RandomStructDir.bin";

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

filename[]是堆栈上的固定长度数组。发生错误时,您尝试连接到它。这可能只会导致更严重的错误,因为它是未定义的行为 - 您正在摧毁堆栈。

答案 2 :(得分:0)

在递归函数中,如果没有匹配元素,我看不到任何终止案例。

答案 3 :(得分:0)

  

我的堆栈框架已损坏

看起来非常像你声明了一个对于堆栈来说太大的变量。而不是

int largeArray[1000][1000];

将其声明为指针

int *largeArray[1000][1000];

当然,代码中的更改是必要的。