c - 读取 C 中的访问冲突,试图找到源
问题描述
伙计们。我有一个项目,给了我一些椅子,一些遮阳伞,以及椅子的位置。我认为必须找到所有遮阳伞的最佳宽度(彼此相等)以覆盖每把椅子。我编写了这段代码,适用于分配文件中的示例案例(它很乱,但它有效):
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void search();
int* constructParasols();
int check();
void draw();
int main(void)
{
int n, k, totalSize;
scanf("%d", &n);
printf("\n");
scanf("%d", &k);
printf("\n");
int* chairs = (int*)calloc(n + 1, sizeof(int));
for (int i = 0; i < n; i++)
{
scanf("%d", &chairs[i]);
}
printf("\n");
totalSize = chairs[n - 1];
search(n, k, chairs, totalSize, 0, totalSize/k);
free(chairs);
chairs = NULL;
system("pause");
}
void search(int n, int k, int* chairs, int totalSize, int low, int hi)
{
int mid = (low + hi)/2;
int tempPos = 0;
if (low >= hi - 1)
{
if (check(n, k, low, chairs, constructParasols(k,totalSize,low), k - 2, totalSize - (low * 2), totalSize) == 1)
{
printf("width %d is optimal\n", low);
}
else if (check(n, k, hi, chairs, constructParasols(k, totalSize, hi), k - 2, totalSize - (low * 2), totalSize) == 1)
{
printf("width%d is optimal\n", hi);
}
else
{
printf("no solution found\n");
}
}
else if (check(n, k, mid, chairs, constructParasols(k, totalSize, mid), k - 2, totalSize - (mid * 2), totalSize) == 1)
{
search(n, k, chairs, totalSize, low, mid-1);
}
else
{
search(n, k, chairs, totalSize, mid+1, hi);
}
}
int* constructParasols(int k, int totalSize, int width)
{
int* parasols = (int*)calloc(k + 1, sizeof(int));
int tempPos = 0;
for (int i = 0; i < k - 1; i++)
{
parasols[i] = tempPos;
tempPos += width;
}
parasols[k - 1] = totalSize - width;
return parasols;
}
int check(int n, int k, int width, int* chairs, int* parasols, int pNum, int maxPos, int totalSize)
{
int* cover = (int*)calloc(totalSize + 1, sizeof(int));
int failed = 0;
for (int i = 0; i < totalSize; i++)
{
cover[i] = 0;
}
if (k<=2)
{
draw(n, k, width, chairs, parasols, totalSize);
for (int i = 0; i < width; i++)
{
cover[i] = 1;
if(k==2) cover[parasols[1] + i] = 1;
}
for (int i = 0; i < n; i++)
{
if (cover[chairs[i] - 1] == 0)
{
failed = 1;
}
}
if (failed == 0)
{
free(cover);
cover = NULL;
free(parasols);
parasols = NULL;
return 1;
}
else
{
free(cover);
cover = NULL;
free(parasols);
parasols = NULL;
return 0;
}
}
draw(n, k, width, chairs, parasols, totalSize);
for (int i = 0; i < k; i++)
{
for (int j = 0; j < width; j++)
{
cover[parasols[i] + j] = 1;
}
}
for (int i = 0; i < n; i++)
{
if (cover[chairs[i]-1] == 0)
{
failed = 1;
}
}
if (failed == 0)
{
free(cover);
cover = NULL;
free(parasols);
parasols = NULL;
return 1;
}
if (pNum <= 1 && parasols[pNum] == maxPos)
{
free(cover);
cover = NULL;
free(parasols);
parasols = NULL;
return 0;
}
else if (parasols[pNum] == maxPos)
{
free(cover);
cover = NULL;
return check(n, k, width, chairs, parasols, pNum - 1, maxPos - width, totalSize);
}
else
{
free(cover);
cover = NULL;
parasols[pNum]++;
return check(n, k, width, chairs, parasols, pNum, maxPos, totalSize);
}
}
void draw(int n, int k, int width, int* chairs, int* parasols, int totalSize)
{
int* dCover = (int*)calloc(totalSize, sizeof(int));
int* chairPos = (int*)calloc(totalSize, sizeof(int));
for (int i = 0; i < totalSize; i++)
{
dCover[i] = 0;
chairPos[i] = 0;
}
for (int i = 0; i < k; i++)
{
for (int j = 0; j < width; j++)
{
if (dCover[parasols[i] + j] >= 1) dCover[parasols[i] + j] = 2;
else dCover[parasols[i] + j] = 1;
}
}
for (int i = 0; i < n; i++)
{
chairPos[chairs[i]-1] = 1;
}
for (int i = 0; i <= totalSize; i++)
{
if (dCover[i] == 2)
{
printf("=");
}
else if (dCover[i] == 1)
{
printf("-");
}
else
{
printf(" ");
}
}
printf("\n");
for (int i = 0; i <= totalSize; i++)
{
if (chairPos[i] == 1)
{
printf("|");
}
else
{
printf(" ");
}
}
printf("\n");
free(dCover);
dCover = NULL;
free(chairPos);
chairPos = NULL;
return;
}
(为了清晰和减小尺寸,删除了一些注释和调试打印)
然而,这些只是他将尝试的十个样本中的两个。我想让它们全部正确,因为我是一个关于编程的完美主义者,而且我注意到我检查封面是否有效的方式存在盲点。现在,它将从右侧取出第二把阳伞并逐个空间拖动它并每次检查。一旦它接触到它右侧的阳伞,它就会从左边的下一个阳伞开始,一直这样做,直到只剩下最左边的阳伞,并得出结论认为这种配置不会成功。
这意味着如果我给出一个样本输入,例如 8 4 1 3 6 9 12 15 17 20,它将无法检查阳伞宽度为 4 且间隔均匀的情况。我着手通过改变这个来纠正这个问题:
else
{
free(cover);
cover = NULL;
parasols[pNum]++;
return check(n, k, width, chairs, parasols, pNum, maxPos, totalSize);
}
(这是它试图将阳伞推到左边并重试的地方)到这个:
else
{
printf("freeing cover\n");
free(cover);
cover = NULL;
printf("iteration failed\n");
//parasols[pNum]++;
//return check(n, k, width, chairs, parasols, pNum, maxPos, totalSize);
if (parasols[pNum] != parasols[pNum - 1] + width && check(n, k, width, chairs, parasols, pNum - 1, parasols[pNum]-width, totalSize) == 1)
{
return 1;
}
else
{
parasols[pNum]++;
return check(n, k, width, chairs, parasols, pNum, maxPos, totalSize);
}
}
似乎有道理。只有当我现在运行它时,我才会遇到读取访问冲突。就在这儿:
else dCover[parasols[i] + j] = 1;
d盖。在绘制命令下。
它会抓住阳伞并将其向右移动,检查它,然后将阳伞抓住它的左侧并将其向右移动。正如我所料。只有 在 它引发异常之后。
如果我还原代码,一切都会完美运行。我不知道这与此有何关系-它们完全是两个不同的指针。我正在使用 Visual Studio 2017 来构建它,如果这有所作为的话。有人可以帮我吗?
解决方案
当你释放已经释放的指针时,你会得到这种迷恋。
您可以自由parasols
使用check
并继续使用它而无需重建它。
在这部分代码中:
if (parasols[pNum] != parasols[pNum - 1] + width && check(n, k, width, chairs, parasols, pNum - 1, parasols[pNum]-width, totalSize) == 1)
{
return 1;
}
else
{
parasols[pNum]++;
return check(n, k, width, chairs, parasols, pNum, maxPos, totalSize);
}
check
失败free(parasols)
并返回 0,因此您进入else
并再次使用它 parasols[pNum]++
并在return check(...
没有重建的情况下使用它parasols
。
程序在第二次崩溃,free
但在访问释放的指针时也可能崩溃。
推荐阅读
- ansible - 如何在没有指定主机的情况下运行 Ansible 剧本?
- r - 将 if 条件作为函数参数传递 - 错误未使用的参数
- java - 使用 Spring JpaRepository(由休眠支持),有没有办法根据 GrantedAuthority 有条件地过滤字段?
- sql-server - 如何在使用 TFDUpdateSQL 插入后获取新 AutoInc 字段值的值
- wordpress - 带有 React 的 WordPress:保存和使用通过 fetch 收集的数据
- rx-swift - 致命错误:绑定错误到行为中继:objectDeleted:文件 #2025
- c# - 通过 C# 执行 Oracle 命令 - 错误:ORA-00933:SQL 命令未正确结束
- java - 如何避免 MVEL PropertyAccessExceptions
- java - 到达底部后自动滚动到回收站视图顶部的最佳方法是什么?
- c++ - printw 在主窗口上重叠