【问题标题】:Access Violation Reading Location访问冲突读取位置
【发布时间】:2011-08-21 05:21:53
【问题描述】:

我对 VC++ 有问题,简单地说,我讨厌它哈哈。我的代码在我的 Mac 上似乎运行良好,但是当我尝试在 VC++ 中运行它时,我在调试时收到此错误:

Windows 已在 Assignment1-FINAL.exe 中触发断点。

这可能是由于堆损坏,这表明存在错误 Assignment1-FINAL.exe 或它已加载的任何 DLL。

这也可能是由于用户在按下 F12 的同时 Assignment1-FINAL.exe 有焦点。

我知道我没有按 F12,所以我不确定我为什么会得到这个...然后,当我尝试在 Release 模式下运行它时,我得到这个:

Assignment1-FINAL.exe 中 0x00401473 处的未处理异常: 0xC0000005:访问冲突读取位置0x00347015。

这是我正在使用的代码:

int countPointsAboveThreshold(point * points, double threshold_distance) {
    int i = 1;
    int count = 0;

    while (points[i - 1].end != true) {
        point pointOne = points[i -1];
        point pointTwo = points[i];
        double distance = distanceBetweenTwoPoints(pointOne, pointTwo);

        if (pointTwo.end == true) {
            if (distance > threshold_distance) {
                count++;
                return count;
            } else {
                return count;
            }
        } else if (distance > threshold_distance) {
            count++;
        }
        i++;
    }
    return count;
}

int totalPoints(point * points) {
    int i = 0;
    while (points[i].end != true) {
        i++;
    }
    return i + 1;
}

point * findLongPaths(point * points, double threshold_distance) {
    int i = 1;
    int locationToStore = 0;
    int pointsAboveThreshold = countPointsAboveThreshold(points, threshold_distance);

    point * pointsByThreshold = new point[pointsAboveThreshold];
    pointValues * pointsToCalculate = new pointValues[pointsAboveThreshold];

    while (points[i - 1].end != true && i < pointsAboveThreshold) {
        point pointOne = points[i - 1];
        point pointTwo = points[i];

        //Check to see if the distance is greater than the threshold, if it is store in an array of pointValues
        double distance = distanceBetweenTwoPoints(pointOne, pointTwo);
        if (distance > threshold_distance) {
            pointsToCalculate[i - 1].originalLocation = i - 1;
            pointsToCalculate[i - 1].distance = distance;
            pointsToCalculate[i - 1].final = pointTwo;
            pointsToCalculate[i - 1].stored = false;

            //If the final point has been calculated, break the loop
            if (pointTwo.end == true) {
                pointsToCalculate[i].end = true;
                break;
            } else {
                pointsToCalculate[i - 1].end = false;
                i++;
                continue;
            }
        }
    }

    if (points[0].end == true && pointsAboveThreshold == 0) {
        point emptyPoint;
        emptyPoint.x = 0.0;
        emptyPoint.y = 0.0;
        emptyPoint.end = true;

        pointsByThreshold[0] = emptyPoint;
        return pointsByThreshold;
    }

    //Find the point with the lowest distance
    int j = 2;
    //EDITED
    pointValues pointWithLowest;
    pointWithLowest = pointsToCalculate[0];
    while (pointsToCalculate[j - 1].end != true) {
        for (int k = 1; pointsToCalculate[k - 1].end != true; k++) {
            if (pointsToCalculate[k - 1].stored == true) {
                k++;
                continue;
            } else {
                if (pointsToCalculate[k - 1].distance > pointWithLowest.distance) {
                    pointWithLowest = pointsToCalculate[k - 1];
                    k++;
                    continue;
                } else if (pointsToCalculate[k - 1].distance == pointWithLowest.distance) {
                    if (pointWithLowest.originalLocation < pointsToCalculate[k - 1].originalLocation) {
                        pointWithLowest = pointsToCalculate[k - 1];
                        k++;
                        continue;
                    } else {
                        k++;
                        continue;
                    }
                } else {
                    pointWithLowest.stored = true;
                    pointsByThreshold[locationToStore] = pointWithLowest.final;
                    locationToStore++;
                    break;
                }
            }
        }
        //DEBUGGER STOPS HERE
        j++;
    }
    delete[] pointsToCalculate;
    return pointsByThreshold;
}

这是主要功能:

    point *longest_calculated = findLongPaths(p, 1.1);
std::cout << "Should equal " << longest[1].y << ": " << longest_calculated[1].y;
    delete longest_calculated;
    cin.get();
    return 0;

【问题讨论】:

  • 那么调试器在代码的什么地方停止了?
  • 我加了一条评论,快到结尾了j++;
  • 这里发生了很多事情——你能发布point的定义吗?
  • typedef struct { int x; int y; bool end; } point; typedef struct { int originalLocation; double distance; point final; bool stored; bool end; } pointValues;pointpointValus 的定义
  • 我无法遵循您的代码,因此很难提供建议。但是通过带有一些组成值的调试器运行,我在最后一个 for 循环中遇到了访问冲突。 j 和 locationToStore 的值不断上升,直到我写到我分配的数组的边界之外。显然算法是错误的,但由于我无法遵循它,因此很难建议如何改进它。

标签: c++ loops exception dynamic heap-memory


【解决方案1】:

初步想法: 断言在哪里?您将 countPointsAboveThreshold() 中的 Points* 作为数组访问,但根本不进行边界检查以确保您没有通过数组的结尾。这将是我检查内存踩踏动作的第一个领域。此外,直接指针调用非常 C。哎呀,您没有在任何数组调用中检查边界。危险...

长度为 0 的新数组可能安全也可能不安全。我会小心的。

见鬼,每当我在声明中看到 [i - 1] 时都会感到紧张。在 i == 0 处很容易阅读垃圾

i,j,k 循环与四重嵌套 ifs 与 continue 和 break 混合?不。重新思考这个逻辑。太复杂了。

您将提前返回在 pointsToCalculate[] 中分配的内存。那里有内存泄漏。

我是否可以建议将您的最后一个函数分成多个部分以简化逻辑?

我讨厌 K&R 风格的括号。不过你的选择 - 不是在这里开始那场圣战:P

除此之外,我会采用我的第一个建议,并确保始终设置结束布尔值并且不会超出范围。如前所述,stl::vector 和一些引用(最好是 const)在这里是你的朋友。

【讨论】:

  • 新建一个长度为零的数组是非常安全的。
  • 我曾想过这一点——但无论如何我都不会这样做。有点像释放 NULL 是有效的......
【解决方案2】:

您将其发布为 C++,但它似乎很少使用 C++ 真正的全部内容:对象。这段代码读起来更像 C。

只是一些注释:

  1. 使用 C++,您无需执行 typedef struct {...} point,执行 struct point {...} 即可完成您想要执行的操作。
  2. 如果您使用stl::vector 而不是c 数组,那么您的循环将变得更加简单,您将不再需要您的函数totalPoints()。你也可以从pointpointValues中去掉成员变量end
  3. 您无缘无故地在堆上而不是在堆栈上创建了很多变量。使用stl::vector(或其他标准容器)、局部变量和引用,您可以大大简化内存管理并避免此类奇怪的崩溃。

我将更深入地研究您的代码,看看是否可以为您提供一些更具体的指导,但您确实应该进一步阅读 C++ 提供的优于 C 的内容。我会看看 cplusplus.comC++ FAQ。还有一些优秀的书籍推荐here

【讨论】:

  • 离题。他没有要求上编程风格的课程。
  • 是的,没错。我只是想给出我认为能让他最接近目标的建议。如果问题的作者认为它没有帮助,我会删除答案。
  • 他在做功课,代码里很多不好的地方都是导师强加的。不幸的是,这通常是这样。
【解决方案3】:

这部分代码对我来说听起来很奇怪:

if (distance > threshold_distance) {
        pointsToCalculate[i - 1].originalLocation = i - 1;
        pointsToCalculate[i - 1].distance = distance;
        pointsToCalculate[i - 1].final = pointTwo;
        pointsToCalculate[i - 1].stored = false;
...

我认为您需要使用另一个索引变量(除了 i - 1)来填充 pointsToCalculate!

我会像这样重写这部分:

int i = 1;
int index = 0;

// if points[i - 1].end is true how you could access points[i] ?
while (points[i].end != true && i < pointsAboveThreshold) {
    point pointOne = points[i - 1];
    point pointTwo = points[i];

    //Check to see if the distance is greater than the threshold, if it is store in an array of pointValues     
    double distance = distanceBetweenTwoPoints(pointOne, pointTwo);
    if (distance > threshold_distance) {
        pointsToCalculate[index].originalLocation = i - 1;
        pointsToCalculate[index].distance = distance;
        pointsToCalculate[index].final = pointTwo;
        pointsToCalculate[index].stored = false;

        ++ index;
    }

    ++i;
}

pointsToCalculate[index].end = true;

** 另请注意,您的数组中至少需要两个点,否则您将再次遇到访问冲突,因此您需要检查这一点,并且您也需要修复“countPointsAboveThreshold”函数中的相同问题。

请检查语法和拼写错误;)

但我强烈建议也遵循最后两个帖子的建议。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-31
    • 2016-05-28
    • 2017-01-09
    • 2014-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多