lib/sod.h (SOD_DECL): Check that we allocated the right size.
authorMark Wooding <mdw@distorted.org.uk>
Mon, 5 Aug 2019 09:27:42 +0000 (10:27 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Mon, 5 Aug 2019 09:27:42 +0000 (10:27 +0100)
doc/runtime.tex
lib/sod-hosted.c
lib/sod.3
lib/sod.h

index 4f6d277..59b4d72 100644 (file)
@@ -824,6 +824,10 @@ The following macro constructs an instance with automatic storage duration.
   instance should be torn down before this happens, using the
   \descref{fun}{sod_teardown}[function].  It may be appropriate to @|assert|
   that the object is ready for deallocation at this time.
+
+  By default, this macro will abort the program if the size allocated for the
+  instance doesn't match the size required by the class object; set
+  \descref{feat}{SOD_RECKLESS} to inhibit this check.
 \end{describe}
 
 \subsubsection{Dynamic allocation}
index 961aa22..5b6e378 100644 (file)
 
 /*----- Header files ------------------------------------------------------*/
 
+#include <stdio.h>
 #include <stdlib.h>
 
 #include "sod.h"
 
+/*----- Preliminary macros ------------------------------------------------*/
+
+#if __STDC_VERSION__ >= 199901
+#  define PRIuSZ "zu"
+#  define PRINT_SZ(x) (x)
+#else
+#  define PRIuSZ "lu"
+#  define PRINT_SZ(x) ((unsigned long)(x))
+#endif
+
 /*----- Main code ---------------------------------------------------------*/
 
+/* --- @sod__chksz_fail@ --- *
+ *
+ * Arguments:  @const SodClass *cls@ = class we were trying to instantiate
+ *             @size_t sz@ = size allocated
+ *
+ * Returns:    Doesn't.
+ *
+ * Use:                Reports instantiation failure caused by a mismatch between
+ *             the size allocated (@sz@) and the size required for an
+ *             instance of class @cls@.
+ */
+
+SOD__NORETURN void sod__chksz_fail(const SodClass *cls, size_t sz)
+{
+  fprintf(stderr, "INTERNAL ERROR: size mismatch for class `%s': "
+         "%"PRIuSZ" allocated but %"PRIuSZ" required",
+         cls->cls.name, PRINT_SZ(sz), PRINT_SZ(cls->cls.initsz));
+  abort();
+}
+
 /* --- @sod_make@, @sod_makev@ --- *
  *
  * Arguments:  @const SodClass *cls@ = class object for new instance
index de46128..c49378a 100644 (file)
--- a/lib/sod.3
+++ b/lib/sod.3
@@ -494,6 +494,13 @@ It may be appropriate to
 .BR assert (3)
 that the object is ready for deallocation at this time.
 .PP
+By default, this macro will abort the program
+if the size allocated for the instance doesn't match
+the size required by the class object;
+set
+.B SOD_RECKLESS
+to inhibit this check.
+.PP
 The
 .B SOD_MAKE
 macro,
index dd1ee03..eb4a4ed 100644 (file)
--- a/lib/sod.h
+++ b/lib/sod.h
@@ -116,6 +116,19 @@ SOD__VARARGS_MACROS_PREAMBLE
 
 #define SOD__IGNORE(var) ((void)(var))
 
+/* --- @SOD__NORETURN@ --- *
+ *
+ * Use:                Marks functions which are not expected to return.
+ */
+
+#if SOD__GCC_P(2, 5)
+#  define SOD__NORETURN __attribute__((__noreturn__))
+#endif
+
+#ifndef SOD__NORETURN
+#  define SOD__NORETURN
+#endif
+
 /* --- @SOD__PARANOIA@ --- *
  *
  * Arguments:  @cond@ = a condition to check
@@ -307,7 +320,7 @@ struct sod_chain {
 
 /* --- @SOD_DECL@ --- *
  *
- * Arguments:  @cls@ = a class type name
+ * Arguments:  @cls_@ = a class type name
  *             @var@ = a variable name
  *             @keys@ = a @KWARGS(...)@ keyword argument sequence
  *
@@ -315,12 +328,31 @@ struct sod_chain {
  *             @cls@ with automatic lifetime.
  */
 
-#define SOD_DECL(cls, var, keys)                                       \
-  struct cls##__ilayout var##__layout;                                 \
-  cls *var = (cls *)sod_init(cls##__class, &var##__layout, keys)
+#define SOD_DECL(cls_, var, keys)                                      \
+  struct cls_##__ilayout var##__layout;                                        \
+  cls_ *var =                                                          \
+    SOD__PARANOIA(sizeof(var##__layout) == cls_##__class->cls.initsz,  \
+                 (cls_ *)sod_init(cls_##__class, &var##__layout, keys), \
+                 (sod__chksz_fail(cls_##__class, sizeof(var##__layout)), \
+                  (cls_ *)0))
 
 /*----- Functions provided ------------------------------------------------*/
 
+/* --- @sod__chksz_fail@ --- *
+ *
+ * Arguments:  @const SodClass *cls@ = class we were trying to instantiate
+ *             @size_t sz@ = size allocated
+ *
+ * Returns:    Doesn't.
+ *
+ * Use:                Reports instantiation failure caused by a mismatch between
+ *             the size allocated (@sz@) and the size required for an
+ *             instance of class @cls@.
+ */
+
+extern SOD__NORETURN
+  void sod__chksz_fail(const SodClass */*cls*/, size_t /*sz*/);
+
 /* --- @sod_subclassp@ --- *
  *
  * Arguments:  @const SodClass *sub, *super@ = pointers to two classes