From 8c523f59907d2c57cddea80e5f49d036ce4e052e Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Wed, 17 May 2017 15:54:24 -0400 Subject: [PATCH 02/31] FIXME: fix memory leaks --- gcc/json.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 108 insertions(+), 11 deletions(-) diff --git a/gcc/json.c b/gcc/json.c index 16e51c4..a920972 100644 --- a/gcc/json.c +++ b/gcc/json.c @@ -20,14 +20,36 @@ along with GCC; see the file COPYING3. If not see #include "config.h" #include "system.h" #include "coretypes.h" +#include "obstack.h" #include "selftest.h" namespace json { +class value; + class string; + class number; + class object; + class array; + class literal; + +/* FIXME: do we want a context to own everything, or do we want + explicit deallocation? + TODO: how do we run the dtors for the vec/hash_map within object/array ? */ #if 0 class context { + public: + context (); + ~context (); + + string *new_string (const char *buf); + number *new_number (double value); + object *new_object (); + array *new_array (); + + private: + struct obstack m_obstack; }; #endif @@ -47,6 +69,7 @@ enum kind class value { public: + virtual ~value () {} virtual enum kind get_kind () const = 0; }; @@ -55,14 +78,17 @@ class value class object : public value { public: + ~object (); + enum kind get_kind () const FINAL OVERRIDE { return JSON_OBJECT; } value *get (const char *key) const; - void set (const char *key, value *v); + void set (char *key, value *v); private: - hash_map > m_map; + typedef hash_map > map_t; + map_t m_map; }; /* Subclass of value for arrays. */ @@ -70,6 +96,8 @@ class object : public value class array : public value { public: + ~array (); + enum kind get_kind () const FINAL OVERRIDE { return JSON_ARRAY; } unsigned get_length () const { return m_elements.length (); } @@ -100,14 +128,15 @@ class number : public value class string : public value { public: - string (const char *utf8) : m_utf8 (utf8) {} + string (const char *utf8) : m_utf8 (xstrdup (utf8)) {} + ~string () { free (m_utf8); } enum kind get_kind () const FINAL OVERRIDE { return JSON_STRING; } const char *get_string () const { return m_utf8; } private: - const char *m_utf8; + char *m_utf8; }; /* Subclass of value for the literals "true", "false", and "null". */ @@ -125,6 +154,53 @@ class literal : public value /* Implemenation. */ +#if 0 +/* class context. */ + +context::context () +{ + gcc_obstack_init (&m_obstack); +} + +context::~context () +{ + obstack_free (&m_obstack, NULL); +} + +string * +context::new_string (const char *buf) +{ + return new (XOBNEW (&m_obstack, json::string)) json::string (buf); +} + +number * +context::new_number (double value) +{ + return new (XOBNEW (&m_obstack, json::number)) json::number (value); +} + +object * +context::new_object () +{ + return new (XOBNEW (&m_obstack, json::object)) json::object (); +} + +array * +context::new_array () +{ + return new (XOBNEW (&m_obstack, json::array)) json::array (); +} +#endif + +object::~object () +{ + for (map_t::iterator it = m_map.begin (); it != m_map.end (); ++it) + { + free (const_cast ((*it).first)); + delete ((*it).second); + } +} + value * object::get (const char *key) const { @@ -134,12 +210,23 @@ object::get (const char *key) const return NULL; } +/* Takes ownership of KEY and VALUE. */ + void -object::set (const char *key, value *v) +object::set (char *key, value *v) { m_map.put (key, v); } +array::~array () +{ + unsigned i; + value *v; + FOR_EACH_VEC_ELT (m_elements, i, v) + delete v; +} + + /* Parsing decls. */ extern value *parse_utf8_string (const char *utf8); @@ -262,9 +349,12 @@ lexer::consume () dump_token (stderr, &m_next_tokens[0]); fprintf (stderr, "\n"); + if (m_next_tokens[0].id == TOK_STRING) + free (m_next_tokens[0].u.string); + + m_num_next_tokens--; memmove (&m_next_tokens[0], &m_next_tokens[1], sizeof (token) * m_num_next_tokens); - m_num_next_tokens--; } void @@ -536,7 +626,7 @@ parser::parse_value () return parse_object (); else if (tok->id == TOK_STRING) { - string *result = new json::string (tok->u.string); + string *result = new string (tok->u.string); m_lexer.consume (); return result; } @@ -544,7 +634,7 @@ parser::parse_value () return parse_array (); else if (tok->id == TOK_NUMBER) { - number *result = new json::number (tok->u.number); + number *result = new number (tok->u.number); m_lexer.consume (); return result; } @@ -577,7 +667,7 @@ parser::parse_object () tok = m_lexer.peek (); if (tok->id != TOK_STRING) error ("expected string for object key"); - const char *key = tok->u.string; + char *key = xstrdup (tok->u.string); m_lexer.consume (); require (TOK_COLON); @@ -673,6 +763,7 @@ test_parse_string () json::value *jv = parse_utf8_string ("\"foo\""); ASSERT_EQ (JSON_STRING, jv->get_kind ()); ASSERT_STREQ ("foo", ((json::string *)jv)->get_string ()); + delete jv; } static void @@ -681,6 +772,7 @@ test_parse_number () json::value *jv = parse_utf8_string ("42"); ASSERT_EQ (JSON_NUMBER, jv->get_kind ()); ASSERT_EQ (42.0, ((json::number *)jv)->get ()); + delete jv; } static void @@ -696,12 +788,14 @@ test_parse_array () ASSERT_EQ (JSON_NUMBER, element->get_kind ()); ASSERT_EQ (i, ((json::number *)element)->get ()); } + delete jv; } static void test_parse_object () { - json::value *jv = parse_utf8_string ("{\"foo\": \"bar\", \"baz\": [42, 43]}"); + json::value *jv + = parse_utf8_string ("{\"foo\": \"bar\", \"baz\": [42, 43]}"); ASSERT_TRUE (jv != NULL); ASSERT_EQ (JSON_OBJECT, jv->get_kind ()); json::object *jo = static_cast (jv); @@ -723,6 +817,8 @@ test_parse_object () // TODO: error-handling // TODO: partial document + + delete jv; } static void @@ -731,6 +827,7 @@ test_parse_empty_object () json::value *jv = parse_utf8_string ("{}"); ASSERT_TRUE (jv != NULL); ASSERT_EQ (JSON_OBJECT, jv->get_kind ()); + delete jv; } /* Run all of the selftests within this file. */ -- 1.8.5.3