C++ std::调整大小时出现矢量和内存错误

C++ std::调整大小时出现矢量和内存错误,c++,stdvector,C++,Stdvector,我的结构定义如下: struct Edge { int u, v; // vertices Edge() { } Edge(int u, int v) { this->u = u; this->v = v; } }; 还有一个类字段,定义如下 vector<Edge> solution; 当最后一次执行push_back时,我在Visual Studio的调试模式下得到一个错误窗口 [App

我的结构定义如下:

struct Edge
{
    int u, v;   // vertices

    Edge() { }
    Edge(int u, int v)
    {
        this->u = u;
        this->v = v;
    }
};
还有一个类字段,定义如下

vector<Edge> solution;
当最后一次执行
push_back
时,我在Visual Studio的调试模式下得到一个错误窗口

[AppName]已触发断点

调试器转到
malloc.c
,到
\u heap\u alloc
函数的末尾。在第7行之前,向量似乎工作正常。我可以看到调试器中的所有元素。向量似乎在重新分配自身(扩展其大小)时遇到了问题

有趣的是,如果我把这个放在所有的推回之前:

solution.reserve(7);
,正确添加第7条边。更有趣的是,试图为超过22个元素保留空间也会导致上述错误

我做错了什么?如何调试它?应用程序的其余部分没有占用这么多内存,所以我不敢相信堆已经满了


更多的代码,根据要求。这是度量旅行商问题的2-近似算法的一个相当草率的实现。它首先创建一个最小生成树,然后按DFS顺序将顶点(仅索引)添加到
partialSolution
向量

void ApproxTSPSolver::Solve()
{
    // creating a incidence matrix
    SquareMatrix<float> graph(noOfPoints);

    for (int r=0; r<noOfPoints; r++)
    {
        for (int c=0; c<noOfPoints; c++)
        {
            if (r == c)
                graph.SetValue(r, c, MAX);
            else
                graph.SetValue(r, c, points[r].distance(points[c]));
        }
    }

    // finding a minimum spanning tree
    spanningTree = SquareMatrix<bool>(noOfPoints);

    // zeroeing the matrix
    for (int r=0; r<noOfPoints; r++)
        for (int c=0; c<noOfPoints; c++)
            spanningTree.SetValue(r, c, false);

    bool* selected = new bool[noOfPoints];
    memset(selected, 0, noOfPoints*sizeof(bool));
    selected[0] = true; // the first point is initially selected

    float min;
    int minR, minC;

    for (int i=0; i<noOfPoints - 1; i++)
    {
        min = MAX;

        for (int r=0; r<noOfPoints; r++)
        {
            if (selected[r] == false)
                continue;

            for (int c=0; c<noOfPoints; c++)
            {
                if (selected[c] == false && graph.GetValue(r, c) < min)
                {
                    min = graph.GetValue(r, c);
                    minR = r;
                    minC = c;
                }
            }
        }

        selected[minC] = true;
        spanningTree.SetValue(minR, minC, true);
    }

    delete[] selected;

    // traversing the tree
    DFS(0);

    minSol = 0.0f;

    // rewriting the solution to the solver's solution field
    for (int i=0; i<noOfPoints - 1; i++)
    {
        solution.push_back(Edge(partialSolution[i], partialSolution[i + 1]));
        minSol += points[partialSolution[i]].distance(points[partialSolution[i + 1]]);
    }

    solution.push_back(Edge(partialSolution[noOfPoints - 1], partialSolution[0]));
    minSol += points[partialSolution[noOfPoints - 1]].distance(points[partialSolution[0]]);

    cout << endl << minSol << endl;

    solved = true;
}

void ApproxTSPSolver::DFS(int vertex)
{
    bool isPresent = std::find(partialSolution.begin(), partialSolution.end(), vertex)
        != partialSolution.end();

    if (isPresent == false)
        partialSolution.push_back(vertex); // if I comment out this line, the error doesn't occur

    for (int i=0; i<spanningTree.GetSize(); i++)
    {
        if (spanningTree.GetValue(vertex, i) == true)
            DFS(i);
    }
}


class ApproxTSPSolver : public TSPSolver
{
    vector<int> partialSolution;
    SquareMatrix<bool> spanningTree;
    void DFS(int vertex);

public:
    void Solve() override;
};
TSPSolver.c的一部分:

TSPSolver::TSPSolver()
{
    points = NULL;
    solved = false;
}

TSPSolver::~TSPSolver()
{
    if (points)
        delete[] points;
}

void TSPSolver::LoadFromFile(string path)
{
    ifstream input(path);
    string line;
    int nodeID;
    float coordX, coordY;
    bool coords = false;

    minX = numeric_limits<float>::max();
    maxX = numeric_limits<float>::min();
    minY = numeric_limits<float>::max();
    maxY = numeric_limits<float>::min();

    while (input.good())
    {
        if (coords == false)
        {
            getline(input, line);

            if (line == "NODE_COORD_SECTION")
            {
                coords = true;
            }
            else if (line.find("DIMENSION") != string::npos)
            {
                int colonPos = line.find_last_of(":");
                noOfPoints = stoi(line.substr(colonPos + 1));
#ifdef _DEBUG
                cout << noOfPoints << " points" << endl;
#endif

                // allocating memory for this amount of points
                points = new Point[noOfPoints];
            }
        }
        else
        {
            input >> nodeID >> coordX >> coordY;

            points[nodeID - 1].X = coordX;
            points[nodeID - 1].Y = coordY;

            minX = min(minX, coordX);
            maxX = max(maxX, coordX);
            minY = min(minY, coordY);
            maxY = max(maxY, coordY);

            if (nodeID == noOfPoints)
            {
                break;
            }
        }
    }

    input.close();
}
TSPSolver::TSPSolver()
{
点数=零;
已解决=错误;
}
TSPSolver::~TSPSolver()
{
如果(点数)
删除[]点;
}
void TSPSolver::LoadFromFile(字符串路径)
{
ifstream输入(路径);
弦线;
int-nodeID;
浮动coordX,coordY;
布尔坐标=假;
minX=数值限制::max();
maxX=数值限制::min();
minY=数值限制::max();
maxY=数值限制::min();
while(input.good())
{
if(coords==false)
{
getline(输入,行);
如果(行==“节点协调部分”)
{
coords=true;
}
else if(line.find(“维度”)!=string::npos)
{
int colonPos=line.find最后一行(“:”);
noOfPoints=stoi(line.substr(colonPos+1));
#ifdef_调试
cout>coordX>>coordY;
点[nodeID-1].X=coordX;
点[nodeID-1].Y=coordY;
minX=min(minX,coordX);
maxX=max(maxX,coordX);
minY=min(minY,coordY);
maxY=max(maxY,coordY);
if(nodeID==noOfPoints)
{
打破
}
}
}
input.close();
}

这与其说是回答,不如说是评论,但篇幅太有限了

如果您在windows上,请尝试。它可能会检测到错误的内存访问

检测这种访问的另一种方法是重新保存初始化为0的空字符数组

打开声明向量的类,并声明一个字符数组,在向量前后各声明64个字符,并将它们初始化为0!。 然后进入向量代码,在那里生成错误,并检查那些填充数组的内容。如果它们被填充,则有人会写得更多


定位“恶意”访问的一种方法(至少在VC++中)是在填充数组中设置一个数据断点,然后检查调用堆栈。

您可能在不同的位置对
点进行越界访问,例如,这个:

input >> nodeID >> coordX >> coordY;
points[nodeID - 1].X = coordX;
如果输入失败,或者值超出范围怎么办

我建议从代码中删除
new
delete
[]
的所有用法;例如,假设
int*点;
然后用
std::vector points
替换。将所有
[]
访问更改为
.at()
并捕获异常。对所有没有正确复制语义的类禁用复制

然后,您可以更确定这不是内存分配错误、复制错误或越界访问(这是解释您症状的有力候选)

这还可以解决
TSPSolver
当前没有正确的复制语义的问题


做一个SSCCE是非常有用的。你提到有“很多输入”,尝试尽可能减少输入,但仍然会出现问题。SSCCE可以包含输入数据,只要其大小可以管理,您可以发布。正如他们所说,当前您显示的代码太多,但还不够。问题仍然潜伏在您尚未发布的某个地方。

您的代码看起来是正确的。也许您有错误这里是程序中的其他元素,例如写入无效的内存地址。矢量7元素在实际代码中的长度是数千还是数百万?@Cyber,在实际代码中,矢量最初是空的。因此,尝试将第7元素添加到矢量时会发生错误。@PiotrK:您可以尝试以下操作:请使用
Edge(int-uu,int-vv):u(uu),v(vv){}
。它比您当前的构造函数更有效。感谢您的想法。“zero”方法没有返回任何有趣的结果,两个数组仍然充满了0。我无法设置“扫描”超过4个字节的数据断点,这使它们基本上没用。我收到以下错误:“无法设置断点。硬件不支持监视请求的字节数。”。我必须尝试你们建议的工具,也许其中一些工具会告诉我一些事情。
TSPSolver::TSPSolver()
{
    points = NULL;
    solved = false;
}

TSPSolver::~TSPSolver()
{
    if (points)
        delete[] points;
}

void TSPSolver::LoadFromFile(string path)
{
    ifstream input(path);
    string line;
    int nodeID;
    float coordX, coordY;
    bool coords = false;

    minX = numeric_limits<float>::max();
    maxX = numeric_limits<float>::min();
    minY = numeric_limits<float>::max();
    maxY = numeric_limits<float>::min();

    while (input.good())
    {
        if (coords == false)
        {
            getline(input, line);

            if (line == "NODE_COORD_SECTION")
            {
                coords = true;
            }
            else if (line.find("DIMENSION") != string::npos)
            {
                int colonPos = line.find_last_of(":");
                noOfPoints = stoi(line.substr(colonPos + 1));
#ifdef _DEBUG
                cout << noOfPoints << " points" << endl;
#endif

                // allocating memory for this amount of points
                points = new Point[noOfPoints];
            }
        }
        else
        {
            input >> nodeID >> coordX >> coordY;

            points[nodeID - 1].X = coordX;
            points[nodeID - 1].Y = coordY;

            minX = min(minX, coordX);
            maxX = max(maxX, coordX);
            minY = min(minY, coordY);
            maxY = max(maxY, coordY);

            if (nodeID == noOfPoints)
            {
                break;
            }
        }
    }

    input.close();
}
input >> nodeID >> coordX >> coordY;
points[nodeID - 1].X = coordX;