Topic: Safe version of malloc wrapper using C++11 to avoid


Author: Mantosh Kumar <mantosh4u@gmail.com>
Date: Sat, 1 Nov 2014 05:58:20 -0700 (PDT)
Raw View
------=_Part_500_1841120845.1414846700852
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable




*malloc()* is still very important function in C program while writing low=
=20
level library .However we know that this function can create all sorts of=
=20
problem if you are not aware of some of its internal concepts. The argument=
=20
type of *malloc()* is of *size_t* type which is typedef of some unsigned.=
=20
Now if our program passes the argument to malloc() by *signed int* variable=
=20
and if it becomes some negative value due to some reason, we are in big big=
=20
trouble. Because under this situation, system would interpreted as requests=
=20
for huge amounts of space, which will often fail. This would lead to=20
program crash at the point depending on how you have handled/used this=20
returned memory in code.=20

While learning C++11 template metaprogramming and type_traits concepts, I=
=20
wrote small wrapper function of malloc which would avoid such scenario=20
while compiling and report the compilation error.=20

The above program was written for learning purpose and to demonstrate the=
=20
usage of type traits functionality. In C++ way, we should not use naked=20
pointer and use of malloc() as it creates all sort of problem related to=20
memory management. malloc() is taken as example just to show how *we can=20
write better type safer(signed/unsigned conversion) and not to promote the=
=20
usage of malloc()*.


I would also like to know yours opinion about

   - Does the above malloc wrapper function make sense?=20
   - Shall we use it in our program instead of malloc()?=20
   - What could be the disadvantage of above function?



#include<type_traits>#include<cstdlib>
template<typename T>constexpr bool Is_unsigned_number() { return std::is_un=
signed<T>::value; }
template<typename T>void check_unsigned()  {
  static_assert(Is_unsigned_number<T>(), "Non Unsigned Type  Data Passed");=
}
template<typename T>void* my_malloc(T val) {
 check_unsigned<T>();
 return malloc(val);}




Case1
=3D=3D=3D=3D=3D
int main() {
     unsigned int  sz1 =3D 10;
     void* a =3D my_malloc(2*sz1);
     *(int *)a =3D 0;}


Output: Pass




Case2
=3D=3D=3D=3D=3D

int main() {
     void* a =3D my_malloc(-1);
     *(int *)a =3D 0;}


Output: Compilation Error


basic.cpp: In instantiation of =E2=80=98void check_unsigned() [with T =3D i=
nt]=E2=80=99:=20
basic.cpp:14:21: required from =E2=80=98void* my_malloc(T) [with T =3D int]=
=E2=80=99=20
basic.cpp:19:28: required from here basic.cpp:9:3: error: static assertion=
=20
failed: Non Unsigned Type Data Passed static_assert(Is_unsigned_number<T>()=
, "Non=20
Unsigned Type Data Passed"); ^






Case 3
=3D=3D=3D=3D=3D=3D

int main() {
     signed int sz =3D 10;
     void* a =3D my_malloc(sz);
     *(int *)a =3D 0;}



Output: Compilation Error


basic.cpp: In instantiation of =E2=80=98void check_unsigned() [with T =3D i=
nt]=E2=80=99:=20
basic.cpp:14:21: required from =E2=80=98void* my_malloc(T) [with T =3D int]=
=E2=80=99=20
basic.cpp:20:28: required from here basic.cpp:9:3: error: static assertion=
=20
failed: Non Unsigned Type Data Passed static_assert(Is_unsigned_number<T>()=
, "Non=20
Unsigned Type Data Passed"); ^





Obviously Case 3 should have been allowed(as its value is positive) but its=
=20
limitation of this approach(type traits) it checks for the type and not the=
=20
value as these checks happens in the compile time. There would be also 2-3=
=20
different function of my_malloc() instantiated by compiler instead of just=
=20
one.
my_malloc<unsigned int>(unsigned int)=20
my_malloc<unsigned long>(unsigned long)>




--=20

---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.

------=_Part_500_1841120845.1414846700852
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><p><strong><br></strong></p><p><strong>malloc()</strong> i=
s still very important function in C=20
program while writing low level library .However we know that this function=
 can create all sorts of=20
problem if you are not aware of some of its internal concepts. The=20
argument type of <strong>malloc()</strong> is of <strong>size_t</strong> ty=
pe which is typedef of some unsigned. Now if our program passes the argumen=
t to malloc() by <strong>signed int</strong>
 variable and if it becomes some negative value due to some reason, we=20
are in big big trouble. Because under this situation, system would=20
interpreted as requests for huge amounts of space, which will often=20
fail. This would lead to program crash at the point depending on how you
 have handled/used this returned memory in code.

</p><p>While learning C++11 template metaprogramming and type_traits=20
concepts, I wrote small wrapper function of malloc which would avoid=20
such scenario while compiling and report the compilation error. <br></p><br=
>The above program was written for learning purpose and to demonstrate=20
the usage of type traits functionality. In C++ way, we should not use=20
naked pointer and use of malloc() as it creates all sort of problem=20
related to memory management. malloc() is taken as example just to show=20
how <b>we can write better type safer(signed/unsigned conversion) and not=
=20
to promote the usage of malloc()</b>.<br><br><br><p>I would also like to kn=
ow yours opinion about</p>

<ul><li>Does the above malloc wrapper function make sense? </li><li>Shall w=
e use it in our program instead of malloc()? </li><li>What could be the dis=
advantage of above function?</li></ul><code><span class=3D"pun"></span></co=
de><br><br><pre style=3D"" class=3D"default prettyprint prettyprinted"><cod=
e><span class=3D"com">#include</span><span class=3D"str">&lt;type_traits&gt=
;</span><span class=3D"pln">
</span><span class=3D"com">#include</span><span class=3D"str">&lt;cstdlib&g=
t;</span><span class=3D"pln">

</span><span class=3D"kwd">template</span><span class=3D"pun">&lt;</span><s=
pan class=3D"kwd">typename</span><span class=3D"pln"> T</span><span class=
=3D"pun">&gt;</span><span class=3D"pln">
</span><span class=3D"kwd">constexpr</span><span class=3D"pln"> </span><spa=
n class=3D"kwd">bool</span><span class=3D"pln"> </span><span class=3D"typ">=
Is_unsigned_number</span><span class=3D"pun">()</span><span class=3D"pln"> =
</span><span class=3D"pun">{</span><span class=3D"pln"> </span><span class=
=3D"kwd">return</span><span class=3D"pln"> std</span><span class=3D"pun">::=
</span><span class=3D"pln">is_unsigned</span><span class=3D"pun">&lt;</span=
><span class=3D"pln">T</span><span class=3D"pun">&gt;::</span><span class=
=3D"pln">value</span><span class=3D"pun">;</span><span class=3D"pln"> </spa=
n><span class=3D"pun">}</span><span class=3D"pln">

</span><span class=3D"kwd">template</span><span class=3D"pun">&lt;</span><s=
pan class=3D"kwd">typename</span><span class=3D"pln"> T</span><span class=
=3D"pun">&gt;</span><span class=3D"pln">
</span><span class=3D"kwd">void</span><span class=3D"pln"> check_unsigned</=
span><span class=3D"pun">()</span><span class=3D"pln">  </span><span class=
=3D"pun">{</span><span class=3D"pln">
  </span><span class=3D"kwd">static_assert</span><span class=3D"pun">(</spa=
n><span class=3D"typ">Is_unsigned_number</span><span class=3D"pun">&lt;</sp=
an><span class=3D"pln">T</span><span class=3D"pun">&gt;(),</span><span clas=
s=3D"pln"> </span><span class=3D"str">"Non Unsigned Type  Data Passed"</spa=
n><span class=3D"pun">);</span><span class=3D"pln">
</span><span class=3D"pun">}</span><span class=3D"pln">

</span><span class=3D"kwd">template</span><span class=3D"pun">&lt;</span><s=
pan class=3D"kwd">typename</span><span class=3D"pln"> T</span><span class=
=3D"pun">&gt;</span><span class=3D"pln">
</span><span class=3D"kwd">void</span><span class=3D"pun">*</span><span cla=
ss=3D"pln"> my_malloc</span><span class=3D"pun">(</span><span class=3D"pln"=
>T val</span><span class=3D"pun">)</span><span class=3D"pln"> </span><span =
class=3D"pun">{</span><span class=3D"pln">
 check_unsigned</span><span class=3D"pun">&lt;</span><span class=3D"pln">T<=
/span><span class=3D"pun">&gt;();</span><span class=3D"pln">
 </span><span class=3D"kwd">return</span><span class=3D"pln"> malloc</span>=
<span class=3D"pun">(</span><span class=3D"pln">val</span><span class=3D"pu=
n">);</span><span class=3D"pln">
</span><span class=3D"pun">}<br><br><br><br></span></code><br><code><span c=
lass=3D"pun">Case1<br></span></code><code><span class=3D"pun"><code><span c=
lass=3D"kwd">=3D=3D=3D=3D=3D<br>int</span><span class=3D"pln"> main</span><=
span class=3D"pun">()</span><span class=3D"pln"> </span><span class=3D"pun"=
>{</span><span class=3D"pln">
     </span><span class=3D"kwd">unsigned</span><span class=3D"pln"> </span>=
<span class=3D"kwd">int</span><span class=3D"pln">  sz1 </span><span class=
=3D"pun">=3D</span><span class=3D"pln"> </span><span class=3D"lit">10</span=
><span class=3D"pun">;</span><span class=3D"pln">
     </span><span class=3D"kwd">void</span><span class=3D"pun">*</span><spa=
n class=3D"pln"> a </span><span class=3D"pun">=3D</span><span class=3D"pln"=
> my_malloc</span><span class=3D"pun">(</span><span class=3D"lit">2</span><=
span class=3D"pun">*</span><span class=3D"pln">sz1</span><span class=3D"pun=
">);</span><span class=3D"pln">
     </span><span class=3D"pun">*(</span><span class=3D"kwd">int</span><spa=
n class=3D"pln"> </span><span class=3D"pun">*)</span><span class=3D"pln">a =
</span><span class=3D"pun">=3D</span><span class=3D"pln"> </span><span clas=
s=3D"lit">0</span><span class=3D"pun">;</span><span class=3D"pln">
</span><span class=3D"pun">}<br><br><br></span></code></span></code><code><=
span class=3D"pun"><code><span class=3D"pun">Output: Pass<br><br><br><br></=
span></code></span></code><br><code><span class=3D"pun"><code><span class=
=3D"pun">Case2<br>=3D=3D=3D=3D=3D<br></span></code></span></code><br><code>=
<span class=3D"pun"><code><span class=3D"pun"><code><span class=3D"kwd">int=
</span><span class=3D"pln"> main</span><span class=3D"pun">()</span><span c=
lass=3D"pln"> </span><span class=3D"pun">{</span><span class=3D"pln">
     </span><span class=3D"kwd">void</span><span class=3D"pun">*</span><spa=
n class=3D"pln"> a </span><span class=3D"pun">=3D</span><span class=3D"pln"=
> my_malloc</span><span class=3D"pun">(-</span><span class=3D"lit">1</span>=
<span class=3D"pun">);</span><span class=3D"pln">
     </span><span class=3D"pun">*(</span><span class=3D"kwd">int</span><spa=
n class=3D"pln"> </span><span class=3D"pun">*)</span><span class=3D"pln">a =
</span><span class=3D"pun">=3D</span><span class=3D"pln"> </span><span clas=
s=3D"lit">0</span><span class=3D"pun">;</span><span class=3D"pln">
</span><span class=3D"pun">}<br><br><br></span></code></span></code></span>=
</code>Output: Compilation Error
</pre>

<code><span class=3D"pln"><br>basic</span><span class=3D"pun">.</span><span=
 class=3D"pln">cpp</span><span class=3D"pun">:</span><span class=3D"pln"> <=
/span><span class=3D"typ">In</span><span class=3D"pln"> instantiation of </=
span><span class=3D"pun">=E2=80=98</span><span class=3D"kwd">void</span><sp=
an class=3D"pln"> check_unsigned</span><span class=3D"pun">()</span><span c=
lass=3D"pln"> </span><span class=3D"pun">[</span><span class=3D"kwd">with</=
span><span class=3D"pln"> T </span><span class=3D"pun">=3D</span><span clas=
s=3D"pln"> </span><span class=3D"kwd">int</span><span class=3D"pun">]=E2=80=
=99:</span><span class=3D"pln">
<br>basic</span><span class=3D"pun">.</span><span class=3D"pln">cpp</span><=
span class=3D"pun">:</span><span class=3D"lit">14</span><span class=3D"pun"=
>:</span><span class=3D"lit">21</span><span class=3D"pun">:</span><span cla=
ss=3D"pln">   required </span><span class=3D"kwd">from</span><span class=3D=
"pln"> </span><span class=3D"pun">=E2=80=98</span><span class=3D"kwd">void<=
/span><span class=3D"pun">*</span><span class=3D"pln"> my_malloc</span><spa=
n class=3D"pun">(</span><span class=3D"pln">T</span><span class=3D"pun">)</=
span><span class=3D"pln"> </span><span class=3D"pun">[</span><span class=3D=
"kwd">with</span><span class=3D"pln"> T </span><span class=3D"pun">=3D</spa=
n><span class=3D"pln"> </span><span class=3D"kwd">int</span><span class=3D"=
pun">]=E2=80=99</span><span class=3D"pln">
<br>basic</span><span class=3D"pun">.</span><span class=3D"pln">cpp</span><=
span class=3D"pun">:</span><span class=3D"lit">19</span><span class=3D"pun"=
>:</span><span class=3D"lit">28</span><span class=3D"pun">:</span><span cla=
ss=3D"pln">   required </span><span class=3D"kwd">from</span><span class=3D=
"pln"> here
basic</span><span class=3D"pun">.</span><span class=3D"pln">cpp</span><span=
 class=3D"pun">:</span><span class=3D"lit">9</span><span class=3D"pun">:</s=
pan><span class=3D"lit">3</span><span class=3D"pun">:</span><span class=3D"=
pln"> error</span><span class=3D"pun">:</span><span class=3D"pln"> </span><=
span class=3D"kwd">static</span><span class=3D"pln"> assertion failed</span=
><span class=3D"pun">:</span><span class=3D"pln"> </span><span class=3D"typ=
">Non</span><span class=3D"pln"> </span><span class=3D"typ">Unsigned</span>=
<span class=3D"pln"> </span><span class=3D"typ">Type</span><span class=3D"p=
ln">  </span><span class=3D"typ">Data</span><span class=3D"pln"> </span><sp=
an class=3D"typ">Passed</span><span class=3D"pln">
   </span><span class=3D"kwd">static_assert</span><span class=3D"pun">(</sp=
an><span class=3D"typ">Is_unsigned_number</span><span class=3D"pun">&lt;</s=
pan><span class=3D"pln">T</span><span class=3D"pun">&gt;(),</span><span cla=
ss=3D"pln"> </span><span class=3D"str">"Non Unsigned Type  Data Passed"</sp=
an><span class=3D"pun">);</span><span class=3D"pln">
   </span><span class=3D"pun">^<br><br><br></span></code><pre style=3D"" cl=
ass=3D"default prettyprint prettyprinted"><code><span class=3D"pun"><code><=
span class=3D"pun"><code><span class=3D"pun"></span></code><br><br><br></sp=
an></code></span></code><br><code><span class=3D"pun"><code><span class=3D"=
pun">Case 3<br>=3D=3D=3D=3D=3D=3D<br></span></code></span></code><br><code>=
<span class=3D"pun"><code><span class=3D"pun"><code><span class=3D"kwd">int=
</span><span class=3D"pln"> main</span><span class=3D"pun">()</span><span c=
lass=3D"pln"> </span><span class=3D"pun">{</span><span class=3D"pln">
     </span><span class=3D"kwd">signed</span><span class=3D"pln"> </span><s=
pan class=3D"kwd">int</span><span class=3D"pln"> sz </span><span class=3D"p=
un">=3D</span><span class=3D"pln"> </span><span class=3D"lit">10</span><spa=
n class=3D"pun">;</span><span class=3D"pln">
     </span><span class=3D"kwd">void</span><span class=3D"pun">*</span><spa=
n class=3D"pln"> a </span><span class=3D"pun">=3D</span><span class=3D"pln"=
> my_malloc</span><span class=3D"pun">(</span><span class=3D"pln">sz</span>=
<span class=3D"pun">);</span><span class=3D"pln">
     </span><span class=3D"pun">*(</span><span class=3D"kwd">int</span><spa=
n class=3D"pln"> </span><span class=3D"pun">*)</span><span class=3D"pln">a =
</span><span class=3D"pun">=3D</span><span class=3D"pln"> </span><span clas=
s=3D"lit">0</span><span class=3D"pun">;</span><span class=3D"pln">
</span><span class=3D"pun">}<br><br><br><br></span></code></span></code></s=
pan></code>Output: Compilation Error
</pre>

<code><span class=3D"pln"><br>basic</span><span class=3D"pun">.</span><span=
 class=3D"pln">cpp</span><span class=3D"pun">:</span><span class=3D"pln"> <=
/span><span class=3D"typ">In</span><span class=3D"pln"> instantiation of </=
span><span class=3D"pun">=E2=80=98</span><span class=3D"kwd">void</span><sp=
an class=3D"pln"> check_unsigned</span><span class=3D"pun">()</span><span c=
lass=3D"pln"> </span><span class=3D"pun">[</span><span class=3D"kwd">with</=
span><span class=3D"pln"> T </span><span class=3D"pun">=3D</span><span clas=
s=3D"pln"> </span><span class=3D"kwd">int</span><span class=3D"pun">]=E2=80=
=99:</span><span class=3D"pln">
<br>basic</span><span class=3D"pun">.</span><span class=3D"pln">cpp</span><=
span class=3D"pun">:</span><span class=3D"lit">14</span><span class=3D"pun"=
>:</span><span class=3D"lit">21</span><span class=3D"pun">:</span><span cla=
ss=3D"pln">   required </span><span class=3D"kwd">from</span><span class=3D=
"pln"> </span><span class=3D"pun">=E2=80=98</span><span class=3D"kwd">void<=
/span><span class=3D"pun">*</span><span class=3D"pln"> my_malloc</span><spa=
n class=3D"pun">(</span><span class=3D"pln">T</span><span class=3D"pun">)</=
span><span class=3D"pln"> </span><span class=3D"pun">[</span><span class=3D=
"kwd">with</span><span class=3D"pln"> T </span><span class=3D"pun">=3D</spa=
n><span class=3D"pln"> </span><span class=3D"kwd">int</span><span class=3D"=
pun">]=E2=80=99</span><span class=3D"pln">
<br>basic</span><span class=3D"pun">.</span><span class=3D"pln">cpp</span><=
span class=3D"pun">:</span><span class=3D"lit">20</span><span class=3D"pun"=
>:</span><span class=3D"lit">28</span><span class=3D"pun">:</span><span cla=
ss=3D"pln">   required </span><span class=3D"kwd">from</span><span class=3D=
"pln"> here
basic</span><span class=3D"pun">.</span><span class=3D"pln">cpp</span><span=
 class=3D"pun">:</span><span class=3D"lit">9</span><span class=3D"pun">:</s=
pan><span class=3D"lit">3</span><span class=3D"pun">:</span><span class=3D"=
pln"> error</span><span class=3D"pun">:</span><span class=3D"pln"> </span><=
span class=3D"kwd">static</span><span class=3D"pln"> assertion failed</span=
><span class=3D"pun">:</span><span class=3D"pln"> </span><span class=3D"typ=
">Non</span><span class=3D"pln"> </span><span class=3D"typ">Unsigned</span>=
<span class=3D"pln"> </span><span class=3D"typ">Type</span><span class=3D"p=
ln">  </span><span class=3D"typ">Data</span><span class=3D"pln"> </span><sp=
an class=3D"typ">Passed</span><span class=3D"pln">
   </span><span class=3D"kwd">static_assert</span><span class=3D"pun">(</sp=
an><span class=3D"typ">Is_unsigned_number</span><span class=3D"pun">&lt;</s=
pan><span class=3D"pln">T</span><span class=3D"pun">&gt;(),</span><span cla=
ss=3D"pln"> </span><span class=3D"str">"Non Unsigned Type  Data Passed"</sp=
an><span class=3D"pun">);</span><span class=3D"pln">
   </span><span class=3D"pun">^</span></code><pre style=3D"" class=3D"defau=
lt prettyprint prettyprinted"><code><span class=3D"pun"><code><span class=
=3D"pun"><code><span class=3D"pun"><br></span></code><br><br></span></code>=
</span></code><br></pre><p>Obviously Case 3 should have been allowed(as its=
 value is positive)=20
but its limitation of this approach(type traits) it checks for the type=20
and not the value as these checks happens in the compile time. There=20
would be also 2-3 different function of my_malloc() instantiated by=20
compiler instead of just one.</p>

<code><span class=3D"pln">my_malloc</span><span class=3D"pun">&lt;</span><s=
pan class=3D"kwd">unsigned</span><span class=3D"pln"> </span><span class=3D=
"kwd">int</span><span class=3D"pun">&gt;(</span><span class=3D"kwd">unsigne=
d</span><span class=3D"pln"> </span><span class=3D"kwd">int</span><span cla=
ss=3D"pun">)</span><span class=3D"pln">
<br>my_malloc</span><span class=3D"pun">&lt;</span><span class=3D"kwd">unsi=
gned</span><span class=3D"pln"> </span><span class=3D"kwd">long</span><span=
 class=3D"pun">&gt;(</span><span class=3D"kwd">unsigned</span><span class=
=3D"pln"> </span><span class=3D"kwd">long</span><span class=3D"pun">)&gt;<b=
r><br><br></span></code><pre style=3D"" class=3D"default prettyprint pretty=
printed"><code><span class=3D"pun"><code><span class=3D"pun"></span></code>=
</span></code><br></pre><code><span class=3D"pun"><br></span></code></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_500_1841120845.1414846700852--

.