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}
/*----- 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
#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
/* --- @SOD_DECL@ --- *
*
- * Arguments: @cls@ = a class type name
+ * Arguments: @cls_@ = a class type name
* @var@ = a variable name
* @keys@ = a @KWARGS(...)@ keyword argument sequence
*
* @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