Search code examples
cvisual-studioexceptionheap-memoryc89

Program [X] has triggered a breakpoint, free Heap block [A] modified at [B] after it was freed


I'm developing a little program in ANSI C that generate a graph with dynamics array. When I run it in Visual Studio i get this error: "Program [X] has triggered a breakpoint, and in console is printed: "free Heap block [A] modified at [B] after it was freed". The programs stops on memalloc instruction. I see that this error can occur when memory is freed improperly, but in my case occurs before I call instruction free, and I suppose the problem can be in a wrong memory reallocation.

Code:

    #include "stdafx.h"
    #include <stdlib.h>

    typedef struct TNode TNode;

    struct TNode
    {
        TNode** nodes;
        int nodeCount;
        int index;
    };

    void initialization(int N, TNode * nodes)
    {
        int n = N;
        for (n; n >= 0; --n)
        {
            nodes[n].nodeCount = 0;
            nodes[n].index = n;
        }
    }

    void createGraph(int lastPath, int * J, int * K, TNode * nodes)
    {
        int i = lastPath;
        for (i; i >= 0; --i)
        {
            int nodeJ = J[i];
            int nodeK = K[i];
            //nodeJ
            int lastNode = nodes[nodeJ].nodeCount;
            nodes[nodeJ].nodeCount++;
            if (lastNode == 0)
            {
                nodes[nodeJ].nodes = malloc(sizeof(TNode*) * nodes[nodeJ].nodeCount); //ERROR !!!!
            }
            else
            {
                realloc(nodes[nodeJ].nodes, sizeof(TNode*) * nodes[nodeJ].nodeCount);
            }

            nodes[nodeJ].nodes[lastNode] = &nodes[nodeK];
            //nodeK
            lastNode = nodes[nodeK].nodeCount;
            nodes[nodeK].nodeCount++;
            if (lastNode == 0)
            {
                nodes[nodeK].nodes = malloc(sizeof(TNode*) * nodes[nodeK].nodeCount);
            }
            else
            {
                realloc(nodes[nodeK].nodes, sizeof(TNode*) * nodes[nodeK].nodeCount);
            }
            nodes[nodeK].nodes[lastNode] = &nodes[nodeJ];
        }
    }

    int generate(int J [], int K [], int N){
        int intersections = N + 1;
        TNode *nodes = malloc((intersections) * sizeof(TNode));
        int lastPath = N - 1;
        initialization(N, nodes);
        createGraph(lastPath, J, K, nodes);
        return 0;

    }

    int _tmain(int argc, _TCHAR* argv[])
    {
        int J[8] = { 0, 1, 2, 3, 3, 2, 6, 6 };
        int K[8] = { 1, 2, 3, 4, 5, 6, 8, 7 };
        generate(J, K, 8);

        return 0;
    }

Also I tried to run program on IdeOne: https://ideone.com/fBGEuT and it runs without problem. This makes me suspect that there may be a configuration problem in the compiler.

What do you think is wrong?


Solution

  • This line (and the other realloc-call) is the problem:

    realloc(nodes[nodeJ].nodes, sizeof(TNode*) * nodes[nodeJ].nodeCount);
    

    realloc returns a pointer to the enlarged memory area. This memory area might not be the same memory area as the old one. This can happen if there is no space to enlarge the old memory area as another object is just behind it. Please use something like this instead:

    nodes[nodeJ].nodes = realloc(nodes[nodeJ].nodes, sizeof(TNode*) * nodes[nodeJ].nodeCount);
    

    You might also want to check for errors as both malloc and realloc may fail.

    Your compiler should have emitted a warning for ignoring the result of free. Please do not ignore compiler warnings.