{"id":499,"date":"2022-08-30T15:02:22","date_gmt":"2022-08-30T15:02:22","guid":{"rendered":"https:\/\/unknownerror.org\/index.php\/2013\/11\/09\/c-run-time-type-checking-collection-of-common-programming-errors\/"},"modified":"2022-08-30T15:02:22","modified_gmt":"2022-08-30T15:02:22","slug":"c-run-time-type-checking-collection-of-common-programming-errors","status":"publish","type":"post","link":"https:\/\/unknownerror.org\/index.php\/2022\/08\/30\/c-run-time-type-checking-collection-of-common-programming-errors\/","title":{"rendered":"C run time type checking-Collection of common programming errors"},"content":{"rendered":"<p>I have a C library storing records with a number of fields. Schema are read in from a text file, including the type of each field in the record.<\/p>\n<p>To simplify for question purposes, imagine I have<\/p>\n<pre><code>typedef enum my_type_enum\n{\n    INT32, \/\/32-bit integer\n    MYSTRUCT, \/\/some struct I have, details irrelevant\n    ...\n} my_type_enum;\n\ntypedef struct my_var\n{\n    my_type_enum typetag;\n    unsigned char* data;\n} my_var;\n\nmy_var myrecord[numfields];\n<\/code><\/pre>\n<p>The schema file says whether each field of myrecord should hold an int32_t or a mystruct. My library reads the schema file and for each my_var in myrecord sets the tag and allocates the right amount space for the data.<\/p>\n<p>my_var is opaque and client programs basically use, for simple data<\/p>\n<pre><code>void set(my_var* record, size_t field, void * src)\n{\n    memcpy(record[field].data, src, datatypes[record[field].typetag].size);\n}\n\nint32_t x = 5; \nset(myrecord, 0, &amp;x);\n<\/code><\/pre>\n<p>to store a value in a record, and a similar get() to take things out.<\/p>\n<p>The tagged my_var type allows type checking once data is inside the my_var, but if the schema says record holds three INT32s there is of course nothing to check that src points to an int32_t and not a mystruct when you&#8217;re trying to set() data into that my_var.<\/p>\n<p>Obviously the check needs to take place in something wrapping set(), before the int32_t* or mystruct* is converted to void*. I have seen compile-time checking with typeof() trickery. I feel like what I want probably isn&#8217;t possible, but you never know all the tricks&#8230;<\/p>\n<p>Is there anything I can do better than providing facilities that read a schema at client program compilation time and generate a set_CHECKED() wrapper macro that will give a compiler error if someone tries to copy an int32_t into a my_var tagged to hold mystruct? GCC extensions are fine.<\/p>\n<ol>\n<li>\n<p>Actually, the &#8216;set&#8217; and &#8216;get&#8217; seem to be the correct places to put your checks. If accessing a field with the wrong type is a fatal error, the fix is simple:<\/p>\n<pre><code>void set(my_var* record, size_t field, void * src)\n{\n    if (record[field].typetag != (my_var)src-&gt;typetag) {\n        fprintf(stderr, \"Type mismatch!\\n\");\n        exit(1);\n    }\n    memcpy(record[field].data, src, datatypes[record[field].typetag].size);\n}\n<\/code><\/pre>\n<p>If a type mismatch is not a fatal error, you&#8217;ll need to make set and get return and error code and handle that correctly at the call site.<\/p>\n<p>Note that in C, type information is gone by the time the code is compiled. The &#8216;typetag&#8217; field is the only way you have to know the type of a field.<\/p>\n<p>Of course, if you don&#8217;t need to be able to change the schema without recompiling the library, you could try generating C code from it. That would let you use the compiler&#8217;s type checking at compile time.<\/p>\n<p>(Also: not a big deal, but my_var.data should be a void*, not a char*. This doesn&#8217;t change the correctness of the code but void* tells the reader (and debugger) that the type is unknown.)<\/p>\n<\/li>\n<\/ol>\n<p id=\"rop\"><small>Originally posted 2013-11-09 20:01:02. <\/small><\/p>","protected":false},"excerpt":{"rendered":"<p>I have a C library storing records with a number of fields. Schema are read in from a text file, including the type of each field in the record. To simplify for question purposes, imagine I have typedef enum my_type_enum { INT32, \/\/32-bit integer MYSTRUCT, \/\/some struct I have, details irrelevant &#8230; } my_type_enum; typedef [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-499","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/499","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/comments?post=499"}],"version-history":[{"count":0,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/499\/revisions"}],"wp:attachment":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/media?parent=499"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/categories?post=499"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/tags?post=499"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}