首页 > 解决方案 > C 中的 Valgrind 错误:使用结构、链表和指针。大小为 1 的无效读取和进程以信号 11 的默认操作终止

问题描述

所以我正在编写一个应该链接链表中的数据结构的程序,但我总是得到 valgrind 错误:

Invalid read of size 1
and
Process terminating with default action of signal 11 (SIGSEGV)
 Access not within mapped region at address 0x0

代码的很大一部分已经给了我,我只需要完成它。这是我被要求做的:

读取道路: 编写代码以读取道路并将有关道路的信息连接到城市。道路由起点城市和终点城市指定,两者均以城市名称定义,后跟道路长度。首先,需要为每条道路确定代表起点城市和终点城市的结构。使用 road.h 中的函数 new_road() 创建 Road 结构。 new_road() 返回的结构应添加到道路所在城市的道路列表中,类似于将 City 结构添加到城市名单。请注意,您只能对 roadplan.c 进行更改

这是程序的主文件,我写的部分前面有一个 FIXME 注释:

错误信息一直在底部

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include "salloc.h"
#include "city.h"
#include "road.h"

#define MAX_STRING_LENGTH 100



/*
 * Build the map datastructure
 */
static City *create_map (FILE *data_file)
{
    int num_of_cities, i = 0;
    int num_of_roads = 0;
    City *map = NULL;

    /* Read in city-names   */
    fscanf (data_file, "%d", &num_of_cities);

    for (i = 0; i < num_of_cities; i++)
    {
        char city_name[MAX_STRING_LENGTH + 1];
        City *city;
        City *c;

        fscanf (data_file, "%s", city_name);

        if (find_city (map, city_name) != NULL)
        {
            fprintf (stderr, "City %s already on the map\n", city_name);
            delete_map (map);
            exit (EXIT_FAILURE);
        }
        city = new_city (safe_strdup (city_name));

        if (map == NULL)
            /* This is the first city of the map */
            map = city;
        else {
            /* Find last of city list */
            c = map;
            while (c->next) c = c->next;
            /* And append new city there */
            c -> next = city;
        }
    }

       /* FIXME
         * Read number of roads
         * For each road:
         *    Read origin city name, destination city name and length
         *    Find pointers to orgin city structure and destination city structure
         *    using the function find_city()
         *    Create new road structure using new_road() function
         *    Add it to the list of roads of the origin city.
         */

    /* Read in number-of roads  */
    fscanf (data_file, "%d", &num_of_roads);
    /*read origin city name, destination city name and length for each road
    */
    for (i = 0; i < num_of_roads; i++)
    {
        City road_origin[MAX_STRING_LENGTH + 1]={{0}}, road_destination[MAX_STRING_LENGTH + 1]={{0}};
        unsigned int length = 1;
        Road *road;
        Road *r;
        City *city;
        fscanf (data_file, "%s %s %u", road_origin->name, road_destination->name, &length);
        if (find_city (map, road_origin->name) == NULL)
        {
            fprintf (stderr, "Cannot find city %s on the map\n", road_origin->name);
            exit (EXIT_FAILURE);
        }
        if (find_city (map, road_destination->name) == NULL)
        {
            fprintf (stderr, "Cannot find city %s on the map\n", road_destination->name);
            exit (EXIT_FAILURE);
        }
        road = new_road(road_origin,road_destination, length);
       /*Create new road structure using new_road() function
         *    Add it to the list of roads of the origin city.
         */
        for (city = map; city != NULL; city = city->next)
        {
            if (strcmp(city->name,road_origin->name)==0)
            {
                road_origin->name = city->name;
                if (city->roads == NULL)
                    city->roads=road;/*first road of that city*/
                else
                {
                    r=road;
                    while (r->next) r = r->next;
                    r -> next = road;
                }
            }
            if (strcmp(city->name,road_destination->name)==0)
            {
                road_destination->name = city->name;
            }
        }
    }
    return map;
}

/*
 * Locate city with name city_name on the map
 */
City *find_city (City *list_of_cities, char *city_name)
{
    City *c = list_of_cities;
    while (c != NULL)
    {
        if (strcmp (c->name, city_name) == 0)
            return c;
        c = c->next;
    }
    return NULL;
}

/*
 * Delete a map
 */
static void delete_map (City *map)
{
    City *map_copy;
    while (map != NULL)
    {
        map_copy = map;
        map = map->next;
        delete_city (map_copy);
    }
}

这是给定的 .c 和 .h 文件

道路.c:

#include <stdlib.h>

#include "road.h"
#include "salloc.h"

Road *new_road (City *origin, City *destination, int length)
{
     Road *road     = safe_malloc (sizeof (Road));

     road->origin       = origin;
     road->destination  = destination;
     road->length       = length;
     road->next     = NULL;

     return road;
}


void delete_road (Road *road)
{
    if (road != NULL)
        free (road);
}


void delete_roads (Road *roads)
{
    Road *roads_copy;

    while (roads)
    {
            roads_copy = roads;
        roads = roads->next;
        delete_road (roads_copy);
    }
}

道路.h:

#ifndef _ROAD_H_
#define _ROAD_H_

typedef struct road Road;

#include "city.h"

struct road
{
    City        *origin;
    City        *destination;
    unsigned int    length;
    Road        *next;
};

Road *new_road (City *origin, City *destination, int length);
void delete_road (Road *road);
void delete_roads (Road *roads);

#endif /* _ROAD_H_ */

城市.c:

#include <stdlib.h>

#include "city.h"
#include "salloc.h"

City    *new_city (char *name)
{
    City *city      = safe_malloc (sizeof (City));

    city->name      = name;
    city->roads     = NULL;
    city->next      = NULL;

    return city;
}


void delete_city (City *city)
{
    if (city != NULL)
    {
        delete_roads (city->roads); 
        free (city->name);
        free (city);
    }
}

城市.h:

#ifndef _CITY_H_
#define _CITY_H_

typedef struct city City;

#include "road.h"

struct city
{
    char    *name;
    Road    *roads;
    City    *next;
};


City *new_city (char *name);
void delete_city (City *city);
City *find_city (City *map, char *name);

#endif /*_CITY_H_ */

salloc.c:

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

static void *check_pointer (void *p)
{
    if (p == NULL)
    {
        printf ("Error: out of memory!\n");
        exit (1);
    }
    return p;
}

void *safe_malloc (size_t size)
{
    return check_pointer (malloc (size));
}


char *safe_strdup (const char *string)
{
    return strcpy (safe_malloc (strlen (string) + 1), string);
}

salloc.h:

#include <stdlib.h>

/* These functions provide a way to safely
 * allocate memory
 */

void *safe_malloc (size_t size);
char *safe_strdup (const char *string);

这是我收到的错误消息:

Non-zero exitcode 139
********** runguard stderr follows **********
/usr/bin/runguard: warning: command terminated with signal 11
********** valgrind output follows **********
Memcheck, a memory error detector
Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
Command: /var/lib/domjudge/judgings/ce-codeserver/c8-s38522-j44168/testcase001/execdir/program_d datafile

Invalid read of size 1
   at 0x4C2E2B4: __strcmp_sse42 (vg_replace_strmem.c:852)
   by 0x400B91: find_city (roadplan.c:27)
   by 0x400DEB: create_map (roadplan.c:123)
   by 0x401246: main (roadplan.c:280)
 Address 0x0 is not stack'd, malloc'd or (recently) free'd


Process terminating with default action of signal 11 (SIGSEGV)
 Access not within mapped region at address 0x0
   at 0x4C2E2B4: __strcmp_sse42 (vg_replace_strmem.c:852)
   by 0x400B91: find_city (roadplan.c:27)
   by 0x400DEB: create_map (roadplan.c:123)
   by 0x401246: main (roadplan.c:280)
 If you believe this happened as a result of a stack
 overflow in your program's main thread (unlikely but
 possible), you can try to increase the size of the
 main thread stack using the --main-stacksize= flag.
 The main thread stack size used in this run was 16777216.

HEAP SUMMARY:
    in use at exit: 176 bytes in 11 blocks
  total heap usage: 11 allocs, 0 frees, 176 bytes allocated

LEAK SUMMARY:
   definitely lost: 0 bytes in 0 blocks
   indirectly lost: 0 bytes in 0 blocks
     possibly lost: 0 bytes in 0 blocks
   still reachable: 176 bytes in 11 blocks
        suppressed: 0 bytes in 0 blocks
Rerun with --leak-check=full to see details of leaked memory

For lists of detected and suppressed errors, rerun with: -s
ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

标签: cvalgrind

解决方案


推荐阅读