Coverage Report

Created: 2025-08-28 06:57

/src/proj/src/malloc.cpp
Line
Count
Source (jump to first uncovered line)
1
/******************************************************************************
2
 * Project:  PROJ.4
3
 * Purpose:  Memory management for proj.4.
4
 *           This version includes an implementation of generic destructors,
5
 *           for memory deallocation for the large majority of PJ-objects
6
 *           that do not allocate anything else than the PJ-object itself,
7
 *           and its associated opaque object - i.e. no additional malloc'ed
8
 *           memory inside the opaque object.
9
 *
10
 * Author:   Gerald I. Evenden (Original proj.4 author),
11
 *           Frank Warmerdam   (2000)  pj_malloc?
12
 *           Thomas Knudsen    (2016) - freeup/dealloc parts
13
 *
14
 ******************************************************************************
15
 * Copyright (c) 2000, Frank Warmerdam
16
 * Copyright (c) 2016, Thomas Knudsen / SDFE
17
 *
18
 * Permission is hereby granted, free of charge, to any person obtaining a
19
 * copy of this software and associated documentation files (the "Software"),
20
 * to deal in the Software without restriction, including without limitation
21
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
22
 * and/or sell copies of the Software, and to permit persons to whom the
23
 * Software is furnished to do so, subject to the following conditions:
24
 *
25
 * The above copyright notice and this permission notice shall be included
26
 * in all copies or substantial portions of the Software.
27
 *
28
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
29
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
30
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
31
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
32
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
33
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
34
 * DEALINGS IN THE SOFTWARE.
35
 *****************************************************************************/
36
#ifndef FROM_PROJ_CPP
37
#define FROM_PROJ_CPP
38
#endif
39
40
/* allocate and deallocate memory */
41
/* These routines are used so that applications can readily replace
42
** projection system memory allocation/deallocation call with custom
43
** application procedures.  */
44
45
#include <errno.h>
46
#include <stddef.h>
47
#include <stdlib.h>
48
#include <string.h>
49
50
#include <new>
51
52
#include "proj/internal/io_internal.hpp"
53
54
#include "filemanager.hpp"
55
#include "grids.hpp"
56
#include "proj.h"
57
#include "proj_internal.h"
58
59
using namespace NS_PROJ;
60
61
/**********************************************************************/
62
char *pj_strdup(const char *str)
63
/**********************************************************************/
64
434k
{
65
434k
    size_t len = strlen(str) + 1;
66
434k
    char *dup = static_cast<char *>(malloc(len));
67
434k
    if (dup)
68
434k
        memcpy(dup, str, len);
69
434k
    return dup;
70
434k
}
71
72
/*****************************************************************************/
73
196k
void *free_params(PJ_CONTEXT *ctx, paralist *start, int errlev) {
74
    /*****************************************************************************
75
        Companion to pj_default_destructor (below). Deallocates a linked list
76
        of "+proj=xxx" initialization parameters.
77
78
        Also called from pj_init_ctx when encountering errors before the PJ
79
        proper is allocated.
80
    ******************************************************************************/
81
196k
    paralist *t, *n;
82
2.07M
    for (t = start; t; t = n) {
83
1.88M
        n = t->next;
84
1.88M
        free(t);
85
1.88M
    }
86
196k
    proj_context_errno_set(ctx, errlev);
87
196k
    return (void *)nullptr;
88
196k
}
89
90
/************************************************************************/
91
/*                         proj_destroy()                               */
92
/*                                                                      */
93
/*      This is the application callable entry point for destroying     */
94
/*      a projection definition.  It does work generic to all           */
95
/*      projection types, and then calls the projection specific        */
96
/*      free function, P->destructor(), to do local work.               */
97
/*      In most cases P->destructor()==pj_default_destructor.           */
98
/************************************************************************/
99
100
1.61M
PJ *proj_destroy(PJ *P) {
101
1.61M
    if (nullptr == P || !P->destructor)
102
1.43M
        return nullptr;
103
    /* free projection parameters - all the hard work is done by */
104
    /* pj_default_destructor, which is supposed */
105
    /* to be called as the last step of the local destructor     */
106
    /* pointed to by P->destructor. In most cases,               */
107
    /* pj_default_destructor actually *is* what is pointed to    */
108
182k
    P->destructor(P, proj_errno(P));
109
182k
    return nullptr;
110
1.61M
}
111
112
/*****************************************************************************/
113
// cppcheck-suppress uninitMemberVar
114
302k
PJconsts::PJconsts() : destructor(pj_default_destructor) {}
115
/*****************************************************************************/
116
117
/*****************************************************************************/
118
/*              void PJconsts::copyStateFrom(const PJconsts& other)          */
119
/*****************************************************************************/
120
121
0
void PJconsts::copyStateFrom(const PJconsts &other) {
122
0
    over = other.over;
123
0
    errorIfBestTransformationNotAvailable =
124
0
        other.errorIfBestTransformationNotAvailable;
125
0
    warnIfBestTransformationNotAvailable =
126
0
        other.warnIfBestTransformationNotAvailable;
127
0
    skipNonInstantiable = other.skipNonInstantiable;
128
0
}
129
130
/*****************************************************************************/
131
194k
PJ *pj_new() {
132
    /*****************************************************************************/
133
194k
    return new (std::nothrow) PJ();
134
194k
}
135
136
/*****************************************************************************/
137
194k
PJ *pj_default_destructor(PJ *P, int errlev) { /* Destructor */
138
    /*****************************************************************************
139
        Does memory deallocation for "plain" PJ objects, i.e. that vast majority
140
        of PJs where the opaque object does not contain any additionally
141
        allocated memory below the P->opaque level.
142
    ******************************************************************************/
143
144
    /* Even if P==0, we set the errlev on pj_error and the default context   */
145
    /* Note that both, in the multithreaded case, may then contain undefined */
146
    /* values. This is expected behavior. For MT have one ctx per thread    */
147
194k
    if (0 != errlev)
148
42.3k
        proj_context_errno_set(pj_get_ctx(P), errlev);
149
150
194k
    if (nullptr == P)
151
0
        return nullptr;
152
153
194k
    free(P->def_size);
154
194k
    free(P->def_shape);
155
194k
    free(P->def_spherification);
156
194k
    free(P->def_ellps);
157
158
194k
    delete static_cast<ListOfHGrids *>(P->hgrids_legacy);
159
194k
    delete static_cast<ListOfVGrids *>(P->vgrids_legacy);
160
161
    /* We used to call free( P->catalog ), but this will leak */
162
    /* memory. The safe way to clear catalog and grid is to call */
163
    /* pj_gc_unloadall(pj_get_default_ctx()); and freeate_grids(); */
164
    /* TODO: we should probably have a public pj_cleanup() method to do all */
165
    /* that */
166
167
    /* free the interface to Charles Karney's geodesic library */
168
194k
    free(P->geod);
169
170
    /* free parameter list elements */
171
194k
    free_params(pj_get_ctx(P), P->params, errlev);
172
194k
    free(P->def_full);
173
174
    /* free the cs2cs emulation elements */
175
194k
    proj_destroy(P->axisswap);
176
194k
    proj_destroy(P->helmert);
177
194k
    proj_destroy(P->cart);
178
194k
    proj_destroy(P->cart_wgs84);
179
194k
    proj_destroy(P->hgridshift);
180
194k
    proj_destroy(P->vgridshift);
181
182
194k
    proj_destroy(P->cached_op_for_proj_factors);
183
184
194k
    free(static_cast<struct pj_opaque *>(P->opaque));
185
194k
    delete P;
186
194k
    return nullptr;
187
194k
}
188
189
/*****************************************************************************/
190
0
void proj_cleanup() {
191
    /*****************************************************************************/
192
193
    // Close the database context of the default PJ_CONTEXT
194
0
    auto ctx = pj_get_default_ctx();
195
0
    ctx->iniFileLoaded = false;
196
0
    auto cpp_context = ctx->cpp_context;
197
0
    if (cpp_context) {
198
0
        cpp_context->closeDb();
199
0
    }
200
201
0
    pj_clear_initcache();
202
0
    FileManager::clearMemoryCache();
203
0
    pj_clear_hgridshift_knowngrids_cache();
204
0
    pj_clear_vgridshift_knowngrids_cache();
205
0
    pj_clear_gridshift_knowngrids_cache();
206
0
    pj_clear_sqlite_cache();
207
0
}