B
Bartholomew Simpson
I am writing some C++ wrappers around some legacy C ones - more
specifically, I am providing ctors, dtors and assignment operators for
the C structs.
I have a ton of existing C code that uses these structs. A typical usage
case will be as ff (note the code below is Pseudocode and WILL NOT compile)
//example structs (I have left out the ctors/dtors etc for brevity sake)
struct MyStructA
{
char name[4];
long x;
long y ;
int z ;
};
struct MyStructB
{
long a ;
long b ;
MyStructA * struct_array ;
long allocedsize ;
long numstructs ;
char key[16];
};
struct MyStructC
{
long g ;
long h ;
MyStructB * struct_array ;
long allocedsize ;
long numstructs ;
};
//example C API funcs (ignore null ptrs for now)
void foo_addB(MyStructC* p1, MyStructB* p2)
{
//logic to determine if there is enough room in the
// array for a new struct, if not malloc some more, then
// get position (pos) in array of new struct
memcpy(&p1->struct_array[pos], p2, sizeof(MyStructB));
}
void foo_removeB(MyStructC* p1, const size_t pos)
{
//logic to validate speicified pos (return if !valid)
free(&p1->struct_array[pos]) ;
p1->struct_array[pos] =0 ;
}
//C++ code
bool SomeClass::Method1(MyStructC* arg)
{
//object created on stack
MyStructB b ; //C++ default ctor called (code not shown)
//calls C function
foo_addB( arg, &b) ;
}
bool SomeClass::Method2(MyStructC* arg)
{
//object storage alloced from heap
MyStructB * b = new MyStructB() ; //C++ default ctor called (code
not shown)
//calls C function
foo_addB( arg, b) ;
}
bool SomeClass::Method3(MyStructC* arg)
{
//object storage alloced from heap
MyStructB * b = reinterpret_cast<MyStructB*>(calloc( 1, MyStructB())) ;
//calls C function
foo_addB( arg, b) ;
}
Notes:
======
Because the assignments in the C code are "shallow" copies (C struct
assignment), the copy assignement operators for the structs are also
"shallow", though I have provided explicit methods on the structs to
facilitate "deep" copying.
I have the ff questions:
==========================
Bearing in mind that the C API only carries out a 'shallow' copy which
of the 3 C++ methods above are correct (atleast in the sense that they
will not leak memory, and will not attempt to delete memory twice)?
Here are my observersations/thoughts so far:
SomeClass::Method1()
This will not leak memory (created on stack), but when it goes out of
memory, when foo_removeB() is called, we will be attempting to free an
invalid ptr (also, I suspect, the variable was implicity created by new
behind the scenes - if this is the case trhen there is the [potential?]
issue of destroying with free, an object created with new() ).
SomeClass::Method2()
This will no doubt leak memory - since I am not deleting after the new,
also, there is the issue of destroying an object created with new, by
calling free
SomeClass::Method3()
This seems to be the "best" solution in that memory is alloced from the
heap, and we explicitly specify calloc - so (hopefully), calling free on
this pointer should be ok?
My questions are
==================
i). Is my thinking (so far) correct?
ii). Is there anything I may be overlooking ?
iii). What is the best way to create a struct in C++ code and pass to
the C API functions foo_addB() and foo_removeB()?
specifically, I am providing ctors, dtors and assignment operators for
the C structs.
I have a ton of existing C code that uses these structs. A typical usage
case will be as ff (note the code below is Pseudocode and WILL NOT compile)
//example structs (I have left out the ctors/dtors etc for brevity sake)
struct MyStructA
{
char name[4];
long x;
long y ;
int z ;
};
struct MyStructB
{
long a ;
long b ;
MyStructA * struct_array ;
long allocedsize ;
long numstructs ;
char key[16];
};
struct MyStructC
{
long g ;
long h ;
MyStructB * struct_array ;
long allocedsize ;
long numstructs ;
};
//example C API funcs (ignore null ptrs for now)
void foo_addB(MyStructC* p1, MyStructB* p2)
{
//logic to determine if there is enough room in the
// array for a new struct, if not malloc some more, then
// get position (pos) in array of new struct
memcpy(&p1->struct_array[pos], p2, sizeof(MyStructB));
}
void foo_removeB(MyStructC* p1, const size_t pos)
{
//logic to validate speicified pos (return if !valid)
free(&p1->struct_array[pos]) ;
p1->struct_array[pos] =0 ;
}
//C++ code
bool SomeClass::Method1(MyStructC* arg)
{
//object created on stack
MyStructB b ; //C++ default ctor called (code not shown)
//calls C function
foo_addB( arg, &b) ;
}
bool SomeClass::Method2(MyStructC* arg)
{
//object storage alloced from heap
MyStructB * b = new MyStructB() ; //C++ default ctor called (code
not shown)
//calls C function
foo_addB( arg, b) ;
}
bool SomeClass::Method3(MyStructC* arg)
{
//object storage alloced from heap
MyStructB * b = reinterpret_cast<MyStructB*>(calloc( 1, MyStructB())) ;
//calls C function
foo_addB( arg, b) ;
}
Notes:
======
Because the assignments in the C code are "shallow" copies (C struct
assignment), the copy assignement operators for the structs are also
"shallow", though I have provided explicit methods on the structs to
facilitate "deep" copying.
I have the ff questions:
==========================
Bearing in mind that the C API only carries out a 'shallow' copy which
of the 3 C++ methods above are correct (atleast in the sense that they
will not leak memory, and will not attempt to delete memory twice)?
Here are my observersations/thoughts so far:
SomeClass::Method1()
This will not leak memory (created on stack), but when it goes out of
memory, when foo_removeB() is called, we will be attempting to free an
invalid ptr (also, I suspect, the variable was implicity created by new
behind the scenes - if this is the case trhen there is the [potential?]
issue of destroying with free, an object created with new() ).
SomeClass::Method2()
This will no doubt leak memory - since I am not deleting after the new,
also, there is the issue of destroying an object created with new, by
calling free
SomeClass::Method3()
This seems to be the "best" solution in that memory is alloced from the
heap, and we explicitly specify calloc - so (hopefully), calling free on
this pointer should be ok?
My questions are
==================
i). Is my thinking (so far) correct?
ii). Is there anything I may be overlooking ?
iii). What is the best way to create a struct in C++ code and pass to
the C API functions foo_addB() and foo_removeB()?