{"id":54,"date":"2017-10-16T18:46:07","date_gmt":"2017-10-16T17:46:07","guid":{"rendered":"https:\/\/blog.inplico.uk\/?p=54"},"modified":"2023-06-15T23:41:33","modified_gmt":"2023-06-15T22:41:33","slug":"using-pqexecparams-with-a-char-array","status":"publish","type":"post","link":"https:\/\/blog.inplico.uk\/?p=54","title":{"rendered":"Using PQexecparams with a char** array"},"content":{"rendered":"<p>In short, if you are creating an array of arguments to pass to<strong> PQexecparams()<\/strong> (i.e. char**) then you need to leave enough space to null terminate the array.<\/p>\n<p>Many C programs use a while loop to iterate through an array until they find a null pointer i.e.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\">while (*argv) { \r\n    \/\/foo \r\n    ++argv;\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<p>As soon as *argv = &#8216;\\0&#8217; the loop exits (which is why the array needs a the final element to be null terminated).<\/p>\n<p>It is not documented that PQexecparams() requires a null terminated array of null terminated C-strings, but it does appear as though this is necessary as I got a particularly nasty segmentation fault which took quite a bit of tracking down prior to finding this out.<\/p>\n<p>If you are constructing an array ** that will interact with a C library then it is probably prudent to terminate it thus:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\">#include &lt;string&gt;\r\n#include &lt;vector&gt;\r\n#include &lt;cstring&gt;\r\n#include &lt;iostream&gt;\r\n\r\nstd::vector&lt;std::string&gt; create_array(int nRecords) {\r\n\r\n    std::vector&lt;std::string&gt; myStrings;\r\n    \r\n    for(int i =0; i != nRecords; ++i)\r\n        myStrings.push_back(\"String \" + std::to_string(i +1));\r\n\r\n    return(myStrings);\r\n    \r\n}\r\n\r\nint main() {\r\n\r\n    char \t\t**myCharArray \t        = nullptr;\r\n \tconst int \tnRecords \t\t= 10;\r\n    \r\n \tstd::vector&lt;std::string&gt; vecStrings = create_array(nRecords);\r\n    \r\n    \/\/+1 FOR NULL TERMINATOR\r\n \tmyCharArray = new char *[nRecords +1];\r\n    \r\n    \/\/BUILD CHAR ARRAY\r\n \tint count = 0;\r\n    for(std::string &amp;it : vecStrings) {\r\n \t\tmyCharArray[count] = new char[it.size() +1];\r\n \t\tstrncpy(myCharArray[count], it.c_str(), it.size() +1);\r\n         ++count;\r\n \t}\r\n    \r\n    myCharArray[nRecords] = nullptr;\r\n    \r\n    \/\/OUTPUT\r\n    for(int i =0; i != nRecords; ++i) {\r\n        std::cout &lt;&lt; myCharArray[i] &lt;&lt; std::endl;\r\n    }\r\n    \r\n    \/\/CLEAN UP\r\n    for(int i =0; i &lt;= nRecords; ++i) {\r\n        delete[] myCharArray[i];\r\n        myCharArray[i] = nullptr;\r\n    }\r\n    \r\n    delete[] myCharArray;\r\n    myCharArray = nullptr;\r\n    \r\n}<\/pre>\n<p>Just remember that when iterating through it (particularly when writing) you should use &#8220;for( i != nRecords)&#8221; (i.e. not equal to array size) because you do not want to do not want to overwrite your null terminator.\u00a0 As a general rule it is advisable to terminate the array procedurally after you have loaded it up with data.<\/p>\n<p>What happened on my machine was that <strong>PQexecparams()<\/strong> worked perfectly, but I got a nasty segmentation fault on the next call.\u00a0 On running <strong>gdb<\/strong> and doing a backtrace the final call was to <strong>pqexpbuffer <\/strong>which is part of <strong>libpq<\/strong>.<\/p>\n<p>&nbsp;<\/p>\n<p><strong>NOTE:<\/strong> This is not the first time that I have encountered an array that needs to be terminated with a null pointer, indeed it is in the <strong>Ncursses<\/strong> documentation for both the <strong>FIELD**<\/strong> and <strong>ITEM**<\/strong> arrays so I will be terminating all the arrays that I create in this manner in future.\u00a0 Just make sure that if you do terminate an array that you create enough elements to accommodate the null terminator ( i.e. [nRecords +1] )or you will run into a whole new barrel of monkey fun.<\/p>\n<p>If I am using enums I usually make the last 2 elements TERMINATOR and MAX_ELEMS or something similar<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\">enum {\r\n    ....,\r\n    TERMINATOR,\r\n    MAX_ELEMS\r\n};\r\n\r\nITEM *myArray[MAX_ELEMS];<\/pre>\n<p>This will help to avoid the off by one error which occurs because the array starts at 0 and is a little more explanatory than declaring [MAX_ELEMS +1].<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In short, if you are creating an array of arguments to pass to PQexecparams() (i.e. char**) then you need to leave enough space to null terminate the array. Many C programs use a while loop to iterate through an array until they find a null pointer i.e. while (*argv) { \/\/foo ++argv; } &nbsp; As [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2,4],"tags":[],"class_list":["post-54","post","type-post","status-publish","format-standard","hentry","category-hints-tricks","category-a-series-of-hints-and-tips-when-using-the-postgresql-library-libpq-fe-h"],"_links":{"self":[{"href":"https:\/\/blog.inplico.uk\/index.php?rest_route=\/wp\/v2\/posts\/54","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.inplico.uk\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.inplico.uk\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.inplico.uk\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.inplico.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=54"}],"version-history":[{"count":7,"href":"https:\/\/blog.inplico.uk\/index.php?rest_route=\/wp\/v2\/posts\/54\/revisions"}],"predecessor-version":[{"id":419,"href":"https:\/\/blog.inplico.uk\/index.php?rest_route=\/wp\/v2\/posts\/54\/revisions\/419"}],"wp:attachment":[{"href":"https:\/\/blog.inplico.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=54"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.inplico.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=54"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.inplico.uk\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=54"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}