473,320 Members | 1,974 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

Check to

Hello,

I am trying to expose a C++ class to C clients using a C-compatible wrapper
API. While doing so, I hit a little snag. When a C client deletes one on my
classes using the provided delete method, shouldn't the pointer that passed
to DeleteFoo be null when returned?

A simplified example of my project follows.

Thanks a lot and enjoy the rest of the weekend.

Regards,

Travis Spencer
Portland, OR. USA


#include <iostream>

typedef void* FOO_HANDLE;

void DeleteFoo(FOO_HANDLE f);

class Foo { /* Compiler generated ctor and dtor */ };

int main(int argc, char** argv)
{
// Foos are normally created by C clients using my CreateFoo API
// function, but this is just a demo.
FOO_HANDLE f = new Foo;

DeleteFoo(f);

if (f != NULL)
std::cerr << "f != NULL. Darn!" << std::endl;
else
std::cout << "f == NULL. Cool!" << std::endl;
}

void DeleteFoo(FOO_HANDLE f)
{
delete static_cast<Foo*>(f);
f = NULL;
}
Jul 19 '05 #1
8 1944
Travis Spencer wrote:
Hello,

I am trying to expose a C++ class to C clients using a C-compatible wrapper
API. While doing so, I hit a little snag. When a C client deletes one on my
classes using the provided delete method, shouldn't the pointer that passed
to DeleteFoo be null when returned?

A simplified example of my project follows.

Thanks a lot and enjoy the rest of the weekend.

Regards,

Travis Spencer
Portland, OR. USA


#include <iostream>

typedef void* FOO_HANDLE;

void DeleteFoo(FOO_HANDLE f);

class Foo { /* Compiler generated ctor and dtor */ };

int main(int argc, char** argv)
{
// Foos are normally created by C clients using my CreateFoo API
// function, but this is just a demo.
FOO_HANDLE f = new Foo;

DeleteFoo(f);

if (f != NULL)
std::cerr << "f != NULL. Darn!" << std::endl;
else
std::cout << "f == NULL. Cool!" << std::endl;
}

void DeleteFoo(FOO_HANDLE f)
ITYM:
void DeleteFoo(FOO_HANDLE& f)

because otherwise,
{
delete static_cast<Foo*>(f);
In the above statement, you're deleting the memory pointed to by the
value of the argument `f' (which is local to the function).
f = NULL;
You're now setting the value of this pointer (which is local to the
function DeleteFoo()) to NULL.
}
You need to accept a reference to the pointer if you want to change
its value.

HTH,
--ag
--
Artie Gold -- Austin, Texas

Jul 19 '05 #2

"Travis Spencer" <tr************@hotmail.com> wrote in message
news:bi*********@enews2.newsguy.com...
Hello,

I am trying to expose a C++ class to C clients using a C-compatible wrapper API. While doing so, I hit a little snag. When a C client deletes one on my classes using the provided delete method, shouldn't the pointer that passed to DeleteFoo be null when returned?


No because C and C++ use call by value. A function can never change its
parameters in a way that is visible to the caller under any circumstances.
This is because the function takes a copy of the parameters passed to it,
even if the function changes a parameter, its only a copy of the one that
was supplied by the caller.

Consider

int func(int x)
{
x = 2;
}

int main()
{
int y = 1;
func(y);
cout << y; // outputs 1
}

This is basic C and C++. Your example involves pointers, my examples uses
integers, but there is no difference. Using pointers you can changes what is
pointed to, but that's a completely different situation.

The C++ exception is when references are involved, then a reference to the
oiginal parameter is taken, not a copy, so the function can change the
original parameter.

I don't think there is much point in doing what you are trying to do.
Consider

void DeleteFoo(FOO_HANDLE f);

class Foo { /* Compiler generated ctor and dtor */ };

int main(int argc, char** argv)
{
// Foos are normally created by C clients using my CreateFoo API
// function, but this is just a demo.
FOO_HANDLE f = new Foo;
FOO_HANDLE annoying_copy = f;
DeleteFoo(f);

if (annoying_copy != NULL)
std::cerr << "copy != NULL. Darn!" << std::endl;
else
std::cout << "copy == NULL. Cool!" << std::endl;
}

even if you did make f NULL, there is no way you can touch annoying_copy.
Assuming that your client is going to do things like call functions with
FOO_HANDLE or put FOO_HANDLE into data structures there are always going to
be copies the original FOO_HANDLE.

The only way to do this cleanly is to make FOO_HANDLE a class which has a
destructor. Then the destructor can sort itself out. Since you are
programming for C clients this is not possible, but C programmers have this
sort of headache all the time so they aren't going to mind.

john
Jul 19 '05 #3
Hey Artie,
You need to accept a reference to the pointer if you want to change
its value.


Before posting originally, I did try changing DeleteFoo from

void DeleteFoo(FOO_HANDLE f)

to

void DeleteFoo(FOO_HANDLE* f)

with the same result. Does it have to be a reference? Why wouldn't a
pointer to a pointer work?

Regards,

Travis Spencer
Portland, OR. USA
Jul 19 '05 #4

"Travis Spencer" <tr************@hotmail.com> wrote in message
news:bi*********@enews3.newsguy.com...
Hey Artie,
You need to accept a reference to the pointer if you want to change
its value.


Before posting originally, I did try changing DeleteFoo from

void DeleteFoo(FOO_HANDLE f)

to

void DeleteFoo(FOO_HANDLE* f)

with the same result. Does it have to be a reference? Why wouldn't a
pointer to a pointer work?


It would work. Did you make the correct change to DeleteFoo as well?

void DeleteFoo(FOO_HANDLE* f)
{
delete static_cast<Foo*>(*f);
*f = NULL;
}

Still think you are wasting your time however.

john
Jul 19 '05 #5
Hey John,
Still think you are wasting your time however.


This may be but if so how am I supposed to unit test and regression test
DeleteFoo? What can I check to assure that it successfully deleted its
memory. I was considering this snippet (using CppUnitLite):
TEST(FooAPI, DeleteFoo)
{
HANDLE f = CreateFoo("deepdd");
DeleteFoo(f);
CHECK(p == NULL); // FAILS
}

Any suggestions would be great.
--
Regards,

Travis Spencer
Portland, OR. USA

Jul 19 '05 #6

"Travis Spencer" <tr************@hotmail.com> wrote in message
news:bi********@enews1.newsguy.com...
Hey John,
Still think you are wasting your time however.
This may be but if so how am I supposed to unit test and regression test
DeleteFoo? What can I check to assure that it successfully deleted its
memory. I was considering this snippet (using CppUnitLite):
TEST(FooAPI, DeleteFoo)
{
HANDLE f = CreateFoo("deepdd");
DeleteFoo(f);
CHECK(p == NULL); // FAILS


What is p? Did you mean f?
}

Any suggestions would be great.


There is no way in standard C++ to tell if an arbitrary pointer is pointing
at allocated or deleted memory. One pointer looks pretty much like another.

Maybe there are third party heap management libraries that would give you
the checks you need, but I don't know of any to recommend.

The way I would handle this is not to use pointers, they're too dangerous
for what you want. Why not make HANDLE an integer, which indexes an array of
Foo pointers that is held internally by your API? That might give you a
little more security because you can control how the integers are doled out.
When a Foo object is deleted you set the entry in the array of pointers to
NULL. That gives you an easy check to see if an object has been deleted, at
least until you have to reuse that entry in the array of pointers.

Something like this.

static Foo* array_of_foo[1000];

int CreateFoo()
{
int next_free_slot = ...;
array_of_foo[next_free_slot] = new Foo;
return next_free_slot;
}

void DeleteFoo(int foo)
{
delete array_of_foo[foo];
array_of_foo[foo] = NULL;
}

bool HasBeenDeleted(int foo)
{
return array_of_foo[foo] == NULL;
}

Its not perfect, because sooner of later you will have to reuse integers
that have been used before, but it should give you more control than using
raw pointers.

john
Jul 19 '05 #7
Hello Again John,
TEST(FooAPI, DeleteFoo)
{
HANDLE f = CreateFoo("deepdd");
DeleteFoo(f);
CHECK(p == NULL); // FAILS
What is p? Did you mean f?
}


Did I say p? Ya, I meant f.
Maybe there are third party heap management libraries that would give you
the checks you need,
I don't want to go there. That sounds like way too much trouble for this
little project. Good to know that such things exist though.
The way I would handle this is not to use pointers, they're too dangerous
for what you want. Why not make HANDLE an integer, which indexes an array of Foo pointers that is held internally by your API?
That is so clever!
That gives you an easy check to see if an object has been deleted, at
least until you have to reuse that entry in the array of pointers.
<snip>
Its not perfect, because sooner of later you will have to reuse integers
that have been used before,


Do you mean until all the elements of the array are full of valid pointers
(i.e., array_of_foo[0...999] != NULL). Or do you mean that some mechanism
will need to be put in place to indicate that array_of_foo[52] is available
because it's pointer was deleted (while array_of_foo[0...51] and
array_of_foo[53...999] are not free for example). Would a more complex data
structure like a hash table be appropriate in this situation? Or do I just
need to create an array_of_foo class that will shell out available elements,
create new storage space if its little pool is all used up, etc.

Very neat idea. I think I bum this one off ya.

--
Regards,

Travis Spencer
Portland, OR. USA
Jul 19 '05 #8
>
Its not perfect, because sooner of later you will have to reuse integers
that have been used before,
Do you mean until all the elements of the array are full of valid pointers
(i.e., array_of_foo[0...999] != NULL). Or do you mean that some mechanism
will need to be put in place to indicate that array_of_foo[52] is

available because it's pointer was deleted (while array_of_foo[0...51] and
array_of_foo[53...999] are not free for example).
Either, both, you know your application.
Would a more complex data
structure like a hash table be appropriate in this situation?
Can't see the need for a hash table. A linked list might be appropriate. The
list contains the array slots that are currently free. Saves searching
through the array.
Or do I just
need to create an array_of_foo class that will shell out available elements, create new storage space if its little pool is all used up, etc.

Maybe, there are lots of variations.
Very neat idea. I think I bum this one off ya.


Be my guest.

john
Jul 19 '05 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

17
by: Craig Bailey | last post by:
Someone please explain what alternate universe I fell into this afternoon when PHP started telling me that 2 doesn't equal 2. Not sure about you, but when I run this, it tells me 59001.31 doesn't...
2
by: Askari | last post by:
Hi, How do for do a "select()" on a CheckButton in a menu (make with add_checkbutton(....) )? I can modify title, state, etc but not the "check state". :-( Askari
2
by: Edward | last post by:
The following html / javascript code produces a simple form with check boxes. There is also a checkbox that 'checks all' form checkboxes hotmail style: <html> <head> <title></title> </head>...
7
by: Tony Johnson | last post by:
Can you make a check box very big? It seems like when you drag it bigger the little check is still the same size. Thank you, *** Sent via Developersdex http://www.developersdex.com ***...
2
by: Travis.Box | last post by:
I have an MS Access userform with 16 Check Boxes. Each of the checkboxes has a different option value, which coincides with the Check Box name (eg. cb01.OptionValue = 1). At the bottom of the...
1
by: scprosportsman | last post by:
Please help guys, i am trying to set up a database here at work and im fairly new to access in terms of writing functions and queries and stuff. I have 2 different places on my design that will...
2
by: Chris Davoli | last post by:
How do you enable a check box in the GridView. I selected Checkbox Field in the Columns of the GridView, and the check box shows up in the Grid view, but it is disabled. How do I enable it so I can...
16
by: Brian Tkatch | last post by:
Is there a way to check the order in which SET INTEGRITY needs to be applied? This would be for a script with a dynamic list of TABLEs. B.
5
by: starke1120 | last post by:
Im creating a check in – check out database for RF guns. I have a table that contains models. ID (primary key) Model A table that contains Gun Details ID (primary key) Model_id...
1
by: ghjk | last post by:
my php page has 7 check boxes. I stored checked values to database and retrive as binary values. This is the result array Array ( => 0 => 1 => 0 => 1 => 0 => 0 => 1 ) 1 means checked....
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
0
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.