我有
point.h
和 polygon.h
文件及其关联的 .c
文件。在point.h
// point.h
#ifndef POINT_H
#define POINT_H
typedef struct Point point;
point* alloc_point(void);
void* free_point(point*);
void* init_point(point*, float, float);
void* print_point(const point*);
float get_x_point(const point*);
float get_y_point(const point*);
void* set_x_point(point*, float);
void* set_y_point(point*, float);
#endif
在
point.c
,我有
// point.c
#include <stdlib.h>
#include <stdio.h>
#include "point.h"
#define GET_VALUE_ERROR (2L)
struct Point
{
float x;
float y;
};
point* alloc_point(void)
{
point* pt = malloc(sizeof *pt);
if(NULL == pt)
{
fprintf(stderr, "Could not allocate point. Aborting\n");
return NULL;
}
else
{
return pt;
}
}
void* free_point(point* pt)
{
if(NULL == pt)
{
fprintf(stderr, "Could not free point. Aborting\n");
return NULL;
}
else
{
free(pt);
pt = NULL;
return NULL;
}
}
void* init_point(point* pt, float x, float y)
{
if(NULL == pt)
{
fprintf(stderr, "Cannot initiate point.\n");
return NULL;
}
else
{
pt -> x = x;
pt -> y = y;
return NULL;
}
}
void* print_point(const point* pt)
{
if(NULL == pt)
{
fprintf(stderr, "Cannot print point.\n");
return NULL;
}
else
{
printf("Point at (%f, %f)\n", pt -> x, pt -> y);
return NULL;
}
}
float get_x_point(const point* pt)
{
if(NULL == pt)
{
fprintf(stderr, "Cannot get point.\n");
return GET_VALUE_ERROR;
}
else
{
return pt -> x;
}
}
float get_y_point(const point* pt)
{
if(NULL == pt)
{
fprintf(stderr, "Cannot get point.\n");
return GET_VALUE_ERROR;
}
else
{
return pt -> y;
}
}
void* set_x_point(point* pt, float x)
{
if(NULL == pt)
{
fprintf(stderr, "Cannot get point.\n");
return NULL;
}
else
{
pt -> x = x;
return NULL;
}
}
void* set_y_point(point* pt, float y)
{
if(NULL == pt)
{
fprintf(stderr, "Cannot get point.\n");
return NULL;
}
else
{
pt -> y = y;
return NULL;
}
}
在
polygon.h
时我有
// polygon.h
#ifndef POLYGON_H
#define POLYGON_H
typedef struct Polygon polygon;
polygon* alloc_polygon(unsigned);
void* free_polygon(polygon*);
void* init_polygon(polygon*, unsigned, float, point*);
void* print_polygon(const polygon*);
unsigned get_polygon_nside(const polygon*);
void* set_polygon_nside(polygon*, unsigned);
point* get_polygon_centre(const polygon*);
void* set_polygon_centre(polygon*, point*);
#endif
并且在
polygon.c
我有
// polygon.c
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "point.h"
#include "polygon.h"
#ifndef M_PI
#define M_PI (3.14159265358979323846264338327950288)
#endif
#define GET_NSIDE_ERROR (2U)
struct Polygon
{
unsigned nside;
point* centre;
point** vertices;
};
polygon* alloc_polygon(unsigned nside)
{
polygon* poly = malloc(sizeof(*poly));
if(NULL == poly)
{
fprintf(stderr, "Cannot allocate polygon.\n");
return NULL;
}
else
{
poly -> nside = nside;
poly -> centre = alloc_point();
if(NULL == poly -> centre)
{
fprintf(stderr, "Cannot allocate polygon centre.\n");
free(poly);
poly = NULL;
return NULL;
}
else
{
poly -> vertices = malloc(nside * sizeof(point*));
if(NULL == poly -> vertices)
{
fprintf(stderr, "Cannot allocate polygon vertices.\n");
free(poly -> centre);
poly -> centre = NULL;
free(poly);
poly = NULL;
return NULL;
}
else
{
for(unsigned i = 0; i < nside; i++)
{
poly -> vertices[i] = alloc_point();
if(NULL == poly -> vertices[i])
{
fprintf(stderr, "Cannot allocate node %u.\n", i);
for(unsigned j = 0; j < i; j++)
{
free(poly -> vertices[j]);
poly -> vertices[j] = NULL;
}
free(poly -> centre);
poly -> centre = NULL;
free(poly -> vertices);
poly -> vertices = NULL;
free(poly);
poly = NULL;
}
}
}
}
return poly;
}
}
void* free_polygon(polygon* poly)
{
if(NULL == poly)
{
fprintf(stderr, "Cannot free polygon.\n");
return NULL;
}
else
{
if(NULL == poly -> centre)
{
fprintf(stderr, "Cannot free polygon centre.\n");
return NULL;
}
else
{
free(poly -> centre);
poly -> centre = NULL;
if(NULL == poly -> vertices)
{
fprintf(stderr, "Cannot free polygon vertices.\n");
return NULL;
}
else
{
free(poly -> vertices);
poly -> vertices = NULL;
for(unsigned i = 0; i < poly -> nside; i++)
{
if(NULL == poly -> vertices[i])
{
fprintf(stderr, "Cannot free vertex %u.\n", i);
return NULL;
}
else
{
free(poly -> vertices[i]);
poly -> vertices = NULL;
}
}
}
}
free(poly);
poly = NULL;
}
return NULL;
}
// Rest of implementation
显然,多边形的分配和/或释放不正确。为了看到这一点,我写了这篇
main.c
阅读
#include <stdio.h>
#include "point.h"
#include "polygon.h"
#define EXECUTION_OK (0U)
int main() {
unsigned nside = 3;
float radius = 1.0;
point* centre = alloc_point();
init_point(centre, 0.0, 0.0);
polygon* poly = alloc_polygon(nside);
init_polygon(poly, nside, radius, centre);
free_polygon(poly);
free_point(centre);
return EXECUTION_OK;
}
使用命令
gcc -Wall -Wextra -Wpedantic -Werror -std=c99 .\point.c .\polygon.c .\main.c -o .\main.exe
编译,我的IDE中有一个“红十字”(我使用VSCode
),如图所示(这表明出了问题),我也不知道它来自哪里,也不知道如何解决?
您的程序在
free_polygon()
中出现段错误,因为您在每个 vertices
元素之前释放了 verticies[i]
数组:
free(poly -> vertices);
poly -> vertices = NULL;
for(unsigned i = 0; i < poly -> nside; i++)
{
if(NULL == poly -> vertices[i])
{
fprintf(stderr, "Cannot free vertex %u.\n", i);
return NULL;
}
else
{
free(poly -> vertices[i]);
poly -> vertices = NULL;
}
}
一般来说,您希望以与获取资源相反的顺序释放资源(因此
vertices[i]
在 vertices
之前):
void* free_polygon(polygon* poly) {
if(NULL == poly) {
fprintf(stderr, "Cannot free polygon.\n");
return NULL;
}
if(NULL == poly->vertices) {
fprintf(stderr, "Cannot free polygon vertices.\n");
return NULL;
}
for(unsigned i = 0; i < poly->nside; i++) {
if(NULL == poly->vertices[i]) {
fprintf(stderr, "Cannot free vertex %u.\n", i);
return NULL;
}
free(poly -> vertices[i]);
poly -> vertices[i] = NULL;
}
if(NULL == poly->centre) {
fprintf(stderr, "Cannot free polygon centre.\n");
return NULL;
}
free(poly->centre);
free(poly -> vertices);
free(poly);
return NULL;
}
由于您的函数始终返回
NULL
,请考虑将其返回类型更改为 void
。另外看看是否可以使用 free_polygon()
中的 alloc_polygon()
函数,因为它相当复杂。我通常以某种方式构造我的对象,这样我就可以在任何时候调用 free,并且在 free 期间不会将部分构造的对象视为错误。最后,(不固定)考虑使用命名空间前缀,即 polygon_alloc()
而不是 alloc_polygon()
:
polygon* alloc_polygon(unsigned nside) {
polygon* poly = malloc(sizeof(*poly));
if(!poly) {
fprintf(stderr, "Cannot allocate polygon.\n");
return NULL;
}
poly -> nside = nside;
poly->centre = NULL;
poly->vertices = NULL;
poly -> centre = alloc_point();
if(!poly->centre) {
fprintf(stderr, "Cannot allocate polygon centre.\n");
free_polygon(poly);
return NULL;
}
poly->vertices = malloc(nside * sizeof(point*));
if(!poly->vertices) {
fprintf(stderr, "Cannot allocate polygon vertices.\n");
free_polygon(poly);
return NULL;
}
for(unsigned i = 0; i < nside; i++) {
poly -> vertices[i] = alloc_point();
if(!poly->vertices[i]) {
fprintf(stderr, "Cannot allocate node %u.\n", i);
free_polygon(poly);
return NULL;
}
}
return poly;
}
void free_polygon(polygon* poly) {
if(!poly) return;
if(!poly->vertices) return;
for(unsigned i = 0; i < poly->nside; i++)
free(poly -> vertices[i]);
free(poly->centre);
free(poly ->vertices);
free(poly);
}