C - realloc失败

3
我可能有一个指针问题,但我无法弄清楚是什么问题。 该项目应从文件中读取数字(正常工作),然后将信息添加到动态分配的数组中。
以下是从文件中读取并添加到数组的代码部分: buffer [0]是一个特殊字符,表示下一个输入将用于街道数组。
我已经查看了代码并更改了大约一周的内容,仍然无法弄清楚问题所在。 请注意,第一个插槽运作良好,在第二次重新分配之后,它抛出了“AddStreet”内部的异常,称访问冲突写入位置。 我确信这是我错过或未能理解的非常愚蠢的事情,所以任何帮助都将不胜感激。
输入示例:#20 20 30 20#40 50 40 60
typedef struct street
{
    int start[2];
    int end[2];
}STREET;

void main()
{
int slength=0;
STREET *streets = NULL;
...
ReadFromFile(&streets, people, buildings);
...
}

void ReadFromFile(STREET **pstreets, PERSON *people, BUILDING *buildings)
{
int slength = 0;
...
if(buffer[0] == stre)
    {
        slength += 1;
        *pstreets = (STREET*) realloc(*pstreets, (slength)*sizeof(STREET));
        fscanf(pf, "%d %d %d %d", &a,&b,&c,&d);
        *pstreets = AddStreet(&(*pstreets), slength-1,a,b,c,d);
    }
...
}

STREET* AddStreet(STREET **streets, int length, int bx, int by, int ex, int ey)
{
    if(ValidStreet(bx, by, ex, ey))
    {
        streets[length]->start[0] = bx;
        streets[length]->start[1] = by;
        streets[length]->end[0] = ex;
        streets[length]->end[1] = ey;
    }
    else
    {
        streets[length]->start[0] = ex;
        streets[length]->start[1] = ey;
        streets[length]->end[0] = bx;
        streets[length]->end[1] = by;
    }

return *streets;
}

1
永远不要使用 PTR = realloc( PTR , SIZE);,因为realloc可能会返回NULL,这样你就会出现内存泄漏的情况。 - Marco
@Sneftel 是的,我一直在使用调试器,realloc 似乎没有改变数组的大小(仍然是8),但我认为这是因为它只是一个指针,除非我错了。 - BoobyTrap
2
除了C++迭代器之外,这个(&(*pstreets)是完全没有意义的。现在展示一下STREET的类型声明。由于所有的AddStreet只是修改一个街道,你可以放弃指向指针和长度参数(也许整个函数都可以)。 - WhozCraig
1
@user3652113,您能否发布访问冲突发生的位置? - Marco
1
以及AddStreet的完整主体。你当前的帖子省略了返回值(而且最好有一个返回)。 - WhozCraig
显示剩余5条评论
1个回答

3

您的AddStreet解除引用逻辑有误。您正在从指向指针基址的指针中解除引用length。您需要从它指向的指针中解除引用,以获取实际的街道对象。

streetsSTREET**时,如下所示:

streets[length]->start[0]

说的是“找到从streets开始偏移量为length的指针所在的指针数组,然后解引用该指针”。但是您的数组不是指针数组。事实上,只有一个指针(而您刚好通过地址传递了它)。
这将会达成您想要的效果:
STREET* AddStreet(STREET **streets, int length, int bx, int by, int ex, int ey)
{
    if(ValidStreet(bx, by, ex, ey))
    {
        (*streets)[length].start[0] = bx;
        (*streets)[length].start[1] = by;
        (*streets)[length].end[0] = ex;
        (*streets)[length].end[1] = ey;
    }
    else
    {
        (*streets)[length].start[0] = ex;
        (*streets)[length].start[1] = ey;
        (*streets)[length].end[0] = bx;
        (*streets)[length].end[1] = by;
    }

    return *streets;
}

坦白地说,你一开始就不应该传递指向指针的指针。
void AddStreet(STREET* street, int bx, int by, int ex, int ey)
{
    if(ValidStreet(bx, by, ex, ey))
    {
        street->start[0] = bx;
        street->start[1] = by;
        street->end[0] = ex;
        street->end[1] = ey;
    }
    else
    {
        street->start[0] = ex;
        street->start[1] = ey;
        street->end[0] = bx;
        street->end[1] = by;
    }
}

作为这个被调用:

    fscanf(pf, "%d %d %d %d", &a,&b,&c,&d);
    AddStreet(*pstreets + (slength-1), a,b,c,d);

使用此方法可以正常工作,且出错的可能性大大降低。


哇,太棒了。非常感谢。我一直在想问题是分配方面的。 - BoobyTrap
2
@user3652113 噢,那里也有很多问题。强制转换是不保证的(请阅读此处,它同样适用于realloc),正如d3l所提到的,您应该验证realloc没有返回NULL。但这应该可以帮助您继续前进。很高兴能帮到您。 - WhozCraig
由于某种原因,void版本会出现错误,指出表达式必须具有类类型(每个“street.”行中的“street”)。以前从未见过这种错误。 - BoobyTrap
1
@user3652113 你是指我发布的第二个版本吗?啊,好的。是的,它有问题。已更新。抱歉。 - WhozCraig

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接