Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 旅行商意外分段故障_C_Segmentation Fault_Traveling Salesman - Fatal编程技术网

C 旅行商意外分段故障

C 旅行商意外分段故障,c,segmentation-fault,traveling-salesman,C,Segmentation Fault,Traveling Salesman,我正试图实现我自己的深度优先搜索算法来解决C99中的旅行商问题,但我遇到了一个意想不到的分段错误 我有一小部分节点(大致)对应于英国的一些地方,它们之间的路径是对称的。问题出现在newNode()方法的早期,在该方法中,我创建了一个新节点并设置其初始状态。这涉及到为节点创建一个路径数组,该数组将指定连接的节点及其之间的“距离”,其中每个路径的节点元素初始化为NULL。这些数组比我目前实现的示例图所需的要大得多(请参见MAX\u path),因此以后很容易扩展 在这种情况下,路径数组可以包含16个

我正试图实现我自己的深度优先搜索算法来解决C99中的旅行商问题,但我遇到了一个意想不到的分段错误

我有一小部分节点(大致)对应于英国的一些地方,它们之间的路径是对称的。问题出现在
newNode()
方法的早期,在该方法中,我创建了一个新节点并设置其初始状态。这涉及到为节点创建一个路径数组,该数组将指定连接的节点及其之间的“距离”,其中每个路径的节点元素初始化为NULL。这些数组比我目前实现的示例图所需的要大得多(请参见
MAX\u path
),因此以后很容易扩展

在这种情况下,
路径
数组可以包含16个元素。初始化此数组的FOR循环在
i=3
时引发分段错误。我完全找不到原因。我在代码下面添加了一些来自
gdb
的输出。希望它能有所帮助,或者你可能更喜欢使用自己的方法

谢谢,;任何帮助都将不胜感激

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define NODES 4
#define MAX_PATHS 16

typedef struct _node_t node_t;
typedef struct _path_t path_t;

struct _node_t
{
    char name[64];
    struct _path_t* paths;
};

struct _path_t
{
    struct _node_t* node;
    int dist;
};

node_t* nodes[NODES];

node_t* newNode(char* name)
{
    node_t* toReturn = (node_t*) malloc(sizeof(node_t*));

    if (toReturn == NULL)
    {
        perror("malloc");
        exit(EXIT_FAILURE);
    }

    printf("toReturn (%p)\n", toReturn);

    strcpy(toReturn->name, name);

    toReturn->paths = (path_t*) malloc(sizeof(path_t) * MAX_PATHS);

    if (toReturn->paths == NULL)
    {
        perror("malloc");
        exit(EXIT_FAILURE);
    }

    printf("toReturn->paths (%p)\n", toReturn->paths);

    for (int i = 0; i < MAX_PATHS; i++)
        toReturn->paths[i].node = NULL; /* !!! */

    return toReturn;
}

void addPath(node_t* node1, node_t* node2, int dist)
{
    int i = 0;

    while (i < MAX_PATHS)
    {
        if (node1->paths[i].node == NULL)
        {
            node1->paths[i].node = node2;
            node1->paths[i].dist = dist;
            break;
        }

        i++;
    }

    if (i == MAX_PATHS)
    {
        fprintf(stderr, "Ran out of paths!!\n");
        exit(EXIT_FAILURE);
    }

    i = 0;

    while (i < MAX_PATHS)
    {
        if (node2->paths[i].node == NULL)
        {
            node2->paths[i].node = node1;
            node2->paths[i].dist = dist;
            break;
        }

        i++;
    }

    if (i == MAX_PATHS)
    {
        fprintf(stderr, "Ran out of paths!!\n");
        exit(EXIT_FAILURE);
    }
}

int getNodeIndex(node_t* node)
{
    for (int i = 0; i < NODES; i++)
        if (nodes[i] == node)
            return i;

    return -1;
}

void depthFirstSearch(node_t* node, int* visited, int depth, int length)
{
    printf("%s\n", node->name);

    int i = 0; /* Path pointer */

    int thisVisited[NODES];
    memcpy(thisVisited, visited, sizeof(int) * NODES);

    /* Set this node as visited */

    visited[getNodeIndex(node)] = 1;

    /* Now traverse all connected nodes that haven't been visited */

    while (node->paths[i].node != NULL)
    {
        if (visited[getNodeIndex(node->paths[i].node)] == 0)
            depthFirstSearch(node->paths[i].node, thisVisited, depth + 1,
                                  node->paths[i].dist);

        i++;
    }

    for (int j = 0; j < depth; j++)
        putchar(' ');
}

int main(int argc, char** argv)
{
    nodes[0] = newNode("Liverpool");
    nodes[1] = newNode("London");
    nodes[2] = newNode("Manchester");
    nodes[3] = newNode("Norwich");

    addPath(nodes[0], nodes[1], 212);
    addPath(nodes[0], nodes[2], 34);
    addPath(nodes[1], nodes[2], 208);
    addPath(nodes[1], nodes[3], 114);
    addPath(nodes[2], nodes[3], 191);

    int visited[NODES] = {0};

    depthFirstSearch(nodes[0], visited, 0, 0);

    return EXIT_SUCCESS;
}
在FOR循环之前:

(gdb) p toReturn->paths[0]
$18 = {node = 0x0, dist = 0}
(gdb) p toReturn->paths[1]
$19 = {node = 0x0, dist = 0}
(gdb) p toReturn->paths[2]
$20 = {node = 0x602030, dist = 0} // (I don't understand this value here.)
(gdb) p toReturn->paths[3]
$21 = {node = 0x0, dist = 0}
(gdb) p toReturn->paths[4]
$22 = {node = 0x0, dist = 0}
(gdb) p toReturn->paths[5]
$23 = {node = 0x0, dist = 0}
(gdb) p toReturn->paths[6]
$24 = {node = 0x0, dist = 0}
(gdb) p toReturn->paths[7]
$25 = {node = 0x0, dist = 0}
(gdb) p toReturn->paths[8]
$26 = {node = 0x0, dist = 0}
(gdb) p toReturn->paths[9]
$27 = {node = 0x0, dist = 0}
(gdb) p toReturn->paths[10]
$28 = {node = 0x0, dist = 0}
(gdb) p toReturn->paths[11]
$29 = {node = 0x0, dist = 0}
(gdb) p toReturn->paths[12]
$30 = {node = 0x0, dist = 0}
(gdb) p toReturn->paths[13]
$31 = {node = 0x0, dist = 0}
(gdb) p toReturn->paths[14]
$32 = {node = 0x0, dist = 0}
(gdb) p toReturn->paths[15]
$33 = {node = 0x0, dist = 0}
(gdb) p *toReturn
$36 = {
  name = "Liverpool", '\000' <repeats 15 times>, "\021\001", '\000' <repeats 37 times>, paths = 0x602030}
FOR循环之前的返回状态:

(gdb) p toReturn->paths[0]
$18 = {node = 0x0, dist = 0}
(gdb) p toReturn->paths[1]
$19 = {node = 0x0, dist = 0}
(gdb) p toReturn->paths[2]
$20 = {node = 0x602030, dist = 0} // (I don't understand this value here.)
(gdb) p toReturn->paths[3]
$21 = {node = 0x0, dist = 0}
(gdb) p toReturn->paths[4]
$22 = {node = 0x0, dist = 0}
(gdb) p toReturn->paths[5]
$23 = {node = 0x0, dist = 0}
(gdb) p toReturn->paths[6]
$24 = {node = 0x0, dist = 0}
(gdb) p toReturn->paths[7]
$25 = {node = 0x0, dist = 0}
(gdb) p toReturn->paths[8]
$26 = {node = 0x0, dist = 0}
(gdb) p toReturn->paths[9]
$27 = {node = 0x0, dist = 0}
(gdb) p toReturn->paths[10]
$28 = {node = 0x0, dist = 0}
(gdb) p toReturn->paths[11]
$29 = {node = 0x0, dist = 0}
(gdb) p toReturn->paths[12]
$30 = {node = 0x0, dist = 0}
(gdb) p toReturn->paths[13]
$31 = {node = 0x0, dist = 0}
(gdb) p toReturn->paths[14]
$32 = {node = 0x0, dist = 0}
(gdb) p toReturn->paths[15]
$33 = {node = 0x0, dist = 0}
(gdb) p *toReturn
$36 = {
  name = "Liverpool", '\000' <repeats 15 times>, "\021\001", '\000' <repeats 37 times>, paths = 0x602030}

这看起来不对。您需要分配
节点的大小
而不是
节点*
。当我们这样做时,.

这些比预期的要糟糕得多。@Brian你是什么意思?
getNodeIndex()
中的失败案例(
return-1;
)从未处理过,只是取消了引用。不管它是否是segfault的来源,都要处理它。我的意思是,意外的segfault可能是一个真正的麻烦——比预期的segfault更糟。;)赞成。理想情况下,控件永远不会到达(return-1)语句,但无论如何,我已经用一条错误消息和exit()替换了它。。。是的,谢谢,我想就是这样。犯这样一个小错误是多么烦人啊!所以在这种情况下不使用malloc()会警告我吗?是的,应该是这样。许多学生犯的新手错误使用
malloc(sizeof(*toReturn))
可能会使其更为明显(并且无需更改
node\u t
的名称,或者
toReturn的类型更改时)。
node_t* toReturn = (node_t*) malloc(sizeof(node_t*));