15
15
*/
16
16
17
17
#include <stdio.h>
18
+ #include <stdbool.h>
19
+ #include <stdlib.h>
18
20
#include <string.h>
19
21
22
+ #include <assert.h>
23
+
20
24
#include "yajl/yajl_tree.h"
21
25
22
- static unsigned char fileData [65536 ];
26
+ /* context storage for memory debugging routines */
27
+ typedef struct
28
+ {
29
+ bool do_printfs ;
30
+ unsigned int numFrees ;
31
+ unsigned int numMallocs ;
32
+ /* XXX: we really need a hash table here with per-allocation
33
+ * information to find any missing free() calls */
34
+ } yajlTestMemoryContext ;
35
+
36
+ /* cast void * into context */
37
+ #define TEST_CTX (vptr ) ((yajlTestMemoryContext *) (vptr))
38
+
39
+ static void
40
+ yajlTestFree (void * ctx ,
41
+ void * ptr )
42
+ {
43
+ assert (ptr != NULL );
44
+ TEST_CTX (ctx )-> numFrees ++ ;
45
+ if (TEST_CTX (ctx )-> do_printfs ) {
46
+ fprintf (stderr , "yfree: %p\n" , ptr );
47
+ }
48
+ free (ptr );
49
+ }
50
+
51
+ static void *
52
+ yajlTestMalloc (void * ctx ,
53
+ size_t sz )
54
+ {
55
+ void * rv = NULL ;
56
+
57
+ assert (sz != 0 );
58
+ TEST_CTX (ctx )-> numMallocs ++ ;
59
+ rv = malloc (sz );
60
+ assert (rv != NULL );
61
+ if (TEST_CTX (ctx )-> do_printfs ) {
62
+ fprintf (stderr , "yalloc: %p of %ju\n" , rv , sz );
63
+ }
64
+ return rv ;
65
+ }
66
+
67
+ static void *
68
+ yajlTestRealloc (void * ctx ,
69
+ void * ptr ,
70
+ size_t sz )
71
+ {
72
+ void * rv = NULL ;
73
+
74
+ if (ptr == NULL ) {
75
+ assert (sz != 0 );
76
+ TEST_CTX (ctx )-> numMallocs ++ ;
77
+ } else if (sz == 0 ) {
78
+ TEST_CTX (ctx )-> numFrees ++ ;
79
+ }
80
+ rv = realloc (ptr , sz );
81
+ assert (rv != NULL );
82
+ if (TEST_CTX (ctx )-> do_printfs ) {
83
+ fprintf (stderr , "yrealloc: %p -> %p of %ju\n" , ptr , rv , sz );
84
+ }
85
+ return rv ;
86
+ }
87
+
88
+
89
+ static unsigned char fileData [65536 ]; /* xxx: allocate to size of file, error if stdin can't be stat()ed? */
23
90
24
91
int
25
92
main (void )
@@ -28,35 +95,49 @@ main(void)
28
95
yajl_val node ;
29
96
char errbuf [1024 ];
30
97
31
- /* NUL plug the buffers */
32
- fileData [0 ] = '\0' ;
33
- errbuf [0 ] = '\0' ;
98
+ /* memory allocation debugging: allocate a structure which holds
99
+ * allocation routines */
100
+ yajl_alloc_funcs allocFuncs = {
101
+ yajlTestMalloc ,
102
+ yajlTestRealloc ,
103
+ yajlTestFree ,
104
+ (void * ) NULL
105
+ };
106
+
107
+ /* memory allocation debugging: allocate a structure which collects
108
+ * statistics */
109
+ yajlTestMemoryContext memCtx ;
110
+
111
+ memCtx .do_printfs = false; /* xxx set from a command option */
112
+ memCtx .numMallocs = 0 ;
113
+ memCtx .numFrees = 0 ;
114
+
115
+ allocFuncs .ctx = (void * ) & memCtx ;
116
+ yajl_tree_parse_afs = & allocFuncs ;
34
117
35
118
/* read the entire config file */
36
119
rd = fread ((void * ) fileData , (size_t ) 1 , sizeof (fileData ) - 1 , stdin );
37
120
38
121
/* file read error handling */
39
- if (rd == 0 && !feof (stdin )) {
40
- fprintf ( stderr , "error encountered on file read\n " );
41
- return 1 ;
42
- } else if (rd >= sizeof ( fileData ) - 1 ) {
122
+ if (( rd == 0 && !feof ( stdin )) || ferror (stdin )) {
123
+ perror ( "error encountered on file read" );
124
+ exit ( 1 ) ;
125
+ } else if (! feof ( stdin ) ) {
43
126
fprintf (stderr , "config file too big\n" );
44
- return 1 ;
127
+ exit ( 1 ) ;
45
128
}
129
+ fileData [rd ] = '\0' ;
46
130
47
131
/* we have the whole config file in memory. let's parse it ... */
48
132
node = yajl_tree_parse ((const char * ) fileData , errbuf , sizeof (errbuf ));
49
133
50
134
/* parse error handling */
51
135
if (node == NULL ) {
52
- fprintf (stderr , "parse_error: " );
53
- if (strlen (errbuf )) {
54
- fprintf (stderr , "%s" , errbuf );
55
- } else {
56
- fprintf (stderr , "unknown error" );
57
- }
58
- fprintf (stderr , "\n" );
59
- return 1 ;
136
+ assert (errbuf != NULL );
137
+ fprintf (stderr , "tree_parse_error: %s\n" , errbuf );
138
+ fprintf (stderr , "memory leaks:\t%u\n" , memCtx .numMallocs - memCtx .numFrees );
139
+
140
+ exit (1 );
60
141
}
61
142
62
143
/* ... and extract a nested value from the config file */
@@ -74,5 +155,7 @@ main(void)
74
155
75
156
yajl_tree_free (node );
76
157
77
- return 0 ;
158
+ fprintf (stderr , "memory leaks:\t%u\n" , memCtx .numMallocs - memCtx .numFrees );
159
+
160
+ exit (memCtx .numMallocs - memCtx .numFrees ? 1 : 0 );
78
161
}
0 commit comments