0

edit: SOLVED! thanks to @M OEHM who noticed that I had a pointer to szLine (the code isn't showing here). The trick was to use strcpy to another char* pointer. how did i miss it... :(

I've been debugging this problem for quite a good time now, also searched online and found no help. I would be very grateful if anyone could help me figure out this bug:

I am building a database for a graph, with a while loop reading stdin for commands. Commands can be Add_Vertex and Add_Edge between vertices. I've noticed that between iterations of the while loop, the memory somehow gets changed.

So I made a debug printing function that prints the exact same thing at the end of an iteration and at the beginning of the next one. lo and behold, the prints differ. these are the prints:

____________________________________________________________________
 started new iteration. current status:
        still no keys in the graph
_________ Executing: Add_Vertex v5 -2 -5
finished executing. current status before next iteration of while loop:
        key1 = v5
        first connection of v5 is (null)
____________________________________________________________________
 started new iteration. current status:
        key1 = v5
        first connection of v5 is (null)
_________ Executing: Add_Vertex v4 4 4
finished executing. current status before next iteration of while loop:
        key1 = v4
        first connection of v4 is (null)
        key2 = v5
        first connection of v5 is (null)
____________________________________________________________________
 started new iteration. current status:
        key1 = v4
        first connection of v4 is (null)
        key2 = v5
        first connection of v5 is (null)
_________ Executing: Add_Edge v4 v5
finished executing. current status before next iteration of while loop:
        key1 = v4
        first connection of v4 is v5
        key2 = v5
        first connection of v5 is v4
____________________________________________________________________
 started new iteration. current status:
        key1 = v4
        first connection of v4 is 3 0 5

        key2 = v5
        first connection of v5 is x v3 0 5

_________ Executing: Add_Vertex v3 0 5
finished executing. current status before next iteration of while loop:
        key1 = v3
        first connection of v3 is (null)
        key2 = v4
        first connection of v4 is 3
        key3 = v5
        first connection of v5 is x

notice how the last iteration has different prints than the one before.

this is the source code:

#define MAX_LINE_SIZE 256
int main()
{
    char szLine[MAX_LINE_SIZE];
    char* delimiters = " \t\n";
    char* pszCommand;
    // ...
    PGRAPH pg;

    pg = GraphCreate();

    while (fgets(szLine, MAX_LINE_SIZE, stdin))
    {
printf("________________________________________________________\n     started new iteration. current status:\n");
debugprints(pg);
printf("_________ Executing: %s", szLine);
    pszCommand = strtok(szLine, delimiters);

    if (NULL == pszCommand )
    {
        continue;
    }

    if ( 0 == strcmp(pszCommand, "Add_Vertex") )
    {
        // Add Vertex To graph ...
    }
    else if ( 0 == strcmp(pszCommand, "Add_Edge") )
    {
        // Add The Desired Edge ...
    }
printf("finished executing. current status before next iteration of while loop:\n");
debugprints(pg);
}

GraphDestroy(pg);
return 0;

}

this is the code of debugprints (it just prints the info of the graph):

void debugprints(PGRAPH gr) {
    char* key1 = (char*)ListGetFirstKey(gr->pl);
    char* key2 = (char*)ListGetNextKey(gr->pl,key1);
    char* key3 = (char*)ListGetNextKey(gr->pl,key2);
    PLIST adj_list1 = NULL;
    PLIST adj_list2 = NULL;
    PLIST adj_list3 = NULL;
    if (key1) {
        printf("\tkey1 = %s\n",key1);
        adj_list1 = (PLIST)(((PADJ_LIST)ListGetData(gr->pl,key1))->pEdges);
        if (adj_list1) printf("\tfirst connection of %s is %s\n",key1,(char*)ListGetFirstKey(adj_list1));
        if (key2) {
            printf("\tkey2 = %s\n",key2);
            adj_list2 = (PLIST)(((PADJ_LIST)ListGetData(gr->pl,key2))->pEdges);
            if (adj_list2) printf("\tfirst connection of %s is %s\n",key2,(char*)ListGetFirstKey(adj_list2));
            if (key3) {
                printf("\tkey3 = %s\n",key3);
                adj_list3 = (PLIST)(((PADJ_LIST)ListGetData(gr->pl,key3))->pEdges);
                if (adj_list3) printf("\tfirst connection of %s is %s\n",key3,(char*)ListGetFirstKey(adj_list3));
            }
        }
    } else printf("\tstill no keys in the graph\n");
}

Thanks !!!

alonbe
  • 73
  • 5
  • 5
    The memory gets chenged, because you overwrite it with every call to `fgets`. When you want to save data from the line you have read, you must copy its contents somewhere else, e.g. with `strcpy`. Otherwise you will store a pointer into invalidated memory. (I haven't really looked at all your code, but that seems a likely cause.) – M Oehm May 26 '15 at 19:31
  • Thanks @MOehm , but the memory that gets changed isn't the one that fgets writes to (fgets writes to 'szLine', and what gets changed is dynamically allocated memory) – alonbe May 26 '15 at 19:35
  • In that case you need to post the implementations of `// Add Vertex To graph ...` and `// Add The Desired Edge ...`. – Weather Vane May 26 '15 at 19:37
  • 1
    Don't see any dynamically allocated memory in the code you posted. The problem must be in the code we cannot see. – Retired Ninja May 26 '15 at 19:38
  • 2
    I think your use of strtok is suspect. `man strtok` reports that **Avoid using these functions. If you do use them, note that: These functions modify their first argument**. The way your code is set up, I believe you are scribbling... – pedwards May 26 '15 at 19:39
  • @pedwards good comment, only the command is being passed to functions. I suggest use of `strstr`. `if ( pszCommand == strstr(pszCommand, "Add_Vertex") )` – Weather Vane May 26 '15 at 19:40
  • 1
    @alonbe: That's exaclty what we observe. For example when the line is "Add edge v4 v5", the connection is "v5", which is 12 chars into the line. Then you read the next line into the same memory buffer and get "Add vertex v3 0 5". The old connection is _still_ twelve chars into the line buffer, which in this case is "3 0 5". – M Oehm May 26 '15 at 19:42
  • Solved it! Thanks @MOehm , you were right. I added as a key the pointer to the original string. – alonbe May 26 '15 at 19:50
  • if you create a temporary pointer `char *tmp;` and `tmp = szLine;` (after reading each new line) and them modify `pszCommand = strtok(tmp, delimiters);` I think it will work better. – pedwards May 26 '15 at 19:50

0 Answers0