[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-multimedia
Subject: More smart wrapping for struct types?
From: Stefan Westerfeld <stefan () space ! twc ! de>
Date: 2000-05-26 19:59:02
[Download RAW message or body]
Hi!
I am considering to change the mapping for struct like returncodes to a
wrapped version similar to SmartWrappers as well. I'll play with it this
weekend - looking forward to your comments ;)
The problem:
==================
Every struct you declare inside an IDL file is mapped to a class which
implements it. An example may be
// IDL
struct User {
string login, password;
};
interface AccountManager {
void addUser(User u);
User findUser(string login);
sequence<User> listAllUsers();
};
Then the User type maps to a C++ class, with the following data members:
string login, password;
The functions you saw above map to the following in the generated .cc file:
class AccountManager_base [...] {
[...]
virtual void addUser(const User& u) = 0;
virtual User* findUser(const std::string& login) = 0;
virtual std::vector<User *> * listAllUsers() = 0;
};
While the language binding for addUser is quite good, the next two have
problems with freeing the memory they use. Naive use like this:
1 main()
2 {
3 AccountManager am;
4
5 cout << am.findUser("stefan")->password << endl;
6
7 vector<User *> *users = am.listAllUsers();
8 vector<User *>::iterator i;
9 for(i = users->begin(); i != users->end(); i++)
10 cout << (*i)->name << ", " << (*i)->password << endl;
11 }
will result in massive memory leaks. In line 5, one allocated User*
structure is lost. After line 10, all User* structures in the vector<User*>
and the vector<User*>* itself will never get freed.
Using User* instead of plain User everywhere is however still a good idea
nevertheless, as it cuts down the number of copies that are needed in a few
situations. As struct's like User can contain a lot of data, this is probably
critical.
Possible solution:
========================
What would be possible to resolve these issues is defining two new types.
1) User_ptr:
The class User_ptr would be a wrapper around User*. The following things
should be supported:
- empty construction
assign nothing to the internal User* (lazy creation as in SmartWrappers)
- construction from "const User&"
assign the internal User* a copy of the argument
- construction from User_ptr
share the internal User* with User_ptr
- dereferencing via -> and *
return the internal User*, create if not already assigned
Return codes should return User_ptr instead of plain User*, then, to make
errors freeing contents mostly impossible. Also, vectors which are used quite
a few times in MCOP should store User_ptr instead of User*.
2) User_seq:
The class User_seq would be a wrapper around vector<User_ptr>*, and would be
used in return type situations only. It's operations should be analog to
those User_ptr uses.
Rewritten example:
========================
1 main()
2 {
3 AccountManager am;
4
5 cout << am.findUser("stefan")->password << endl;
6
7 User_seq users = am.listAllUsers(); // only this line of code changed
8 vector<User *>::iterator i;
9 for(i = users->begin(); i != users->end(); i++)
10 cout << (*i)->name << ", " << (*i)->password << endl;
11 }
This example, white having exactly the same effect as the example above,
should not be subject to any memory leaks.
As this is fairly essential, I am looking forward to any comments on the
issue.
Cu... Stefan
--
-* Stefan Westerfeld, stefan@space.twc.de (PGP!), Hamburg/Germany
KDE Developer, project infos at http://space.twc.de/~stefan/kde *-
_______________________________________________
Kde-multimedia mailing list
Kde-multimedia@master.kde.org
http://master.kde.org/mailman/listinfo/kde-multimedia
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic