Help me with my style

Started by
12 comments, last by Nodger 20 years, 5 months ago
Hello all, After many years of sloppy programming, I am finally making the decision to clean up my act. But I need some advice. My language is C++. Here are my questions: 1. I read somewhere that its a bad practice to return pointers. Is this true? Why? 2. If the above is true, what is the preferred method of returning newly created strings of arbitrary length without using classes and without using globals? 3. A technical question: how does the free() function know how many bytes to free? I probably should stop, My doctor says I have the wrists of an 80-year old
Advertisement
1) no it''s not
3) the malloc function allocates some extra bytes before or after the actual memory you allocate.
One problem with returning pointers is that the pointer can become invalid if the object it points to is deleted or moved in memory. This usually won''t happen if you''re just grabbing a pointer for the duration of a function, but it''s generally better not to take any chances.

Also, returning a pointer can violate encapsulation, in that it can give the caller direct access to private member data.

This isn''t to say you can never return a pointer, for example to a block of data such as a string. But you do run the risk of dangling pointers or memory leaks. One solution is to write a smart pointer class, which wraps the regular C++ pointer but adds functionality for keeping track of how many times an object is referenced. When an object''s reference count reaches zero, it is automatically deleted.

I''ve also wondered how free() and delete [] know how much memory to free. I assume the size of the allocation must be stored somewhere...
Well, there''s your answer to no. 3. As to no. 1, you may get some varied opinions :-)
quote:Original post by angry
1) no it''s not


Why do none of the windows api functions return them then?

Alright, I''ll re-phrase question 2: what is the preferred method of returning newly created strings of arbitrary length without using classes and without using globals and without returning pointers?


quote:Original post by angry

3) the malloc function allocates some extra bytes before or after the actual memory you allocate.


That doesnt answer my question
quote:Original post by angry
3) the malloc function allocates some extra bytes before or after the actual memory you allocate.


It should be before if that''s the case, wouldn''t it :-)
quote:Original post by Nodger
quote:Original post by angry

3) the malloc function allocates some extra bytes before or after the actual memory you allocate.


That doesnt answer my question


Yeah it does, but he doesn''t say that it contains the length of the data to come.

<pre>

Memory:
[extra][Yourspace+++++++++++++]
^ ^ This is where your data starts, which malloc returns...
|
+ This is the extra space mallocs creates, but you don''t know about it.
</pre>

I still don''t know if this is the case though.
1. I read somewhere that its a bad practice to return pointers. Is this true? Why?

1. There's a few problems that could arise:
If the pointer is pointing to something that has been allocated inside the function (via new or malloc), who is responsible for free'ing it? Obviously not the function, since it's out of scope. You depend on the one using the function to know that he/she has to free the ressources returned by that function. Usually not a good idea.

If the pointer is pointing to something (a variable for example) used inside the function, it's pointing to a position in memory that is no longer owned by your application. Bad idea.

2. There are usually better solutions.
For data like strings or arrays use std::string and std::vector (or any other container class).
If you absolutely have to allocate memory inside a function and return a pointer to that, use smart pointers.

2. If the above is true, what is the preferred method of returning newly created strings of arbitrary length without using classes and without using globals?

Use classes If you want to avoid classes at all costs, I'd suggest passing the pointer as an argument to the function and work on that.

Or, if you have to modify the pointer, get a pointer to the pointer. Though, I state again, this can very easily be the source of many errors.

But at least it should be better visible to the user of the function that it is modifying/may modify the pointer, and that there might be a need to clean up after the function is done.

From my own experience: Skip the non-class solution to number two. It will work well for a while, but it's really not worth the trouble. Smart pointers and or other classes like std::string really make things easier for you. Especially if the source gets bigger it can be a pain to find out who needs to 'free' what ressource when.

A technical question: how does the free() function know how many bytes to free?
I think there's some kind of look-up table, where the information is stored.

[edited by - Wildfire on November 16, 2003 2:32:34 PM]
How do I set my laser printer on stun?
The memory allocation operators allocates a little extra memory along with the memory you requested which is then used when free/delete is called upon the pointer. This is not very good for your program if you are allocating memory for lots of smaller objects as this extra memory which is required to store the allocation info is eating up the available memory - in situations like this it's much better to allocate a large amount of memory which you can share amongst your objects.

EDIT: it's not bad style to return pointers but you must be careful to avoid return pointers/references to internal data which should only be modified from within its class, if you return a pointer to a private member then programmers using your code can modify that variable to their hearts content - destroying the very idea of making that member private

[edited by - Spudder on November 16, 2003 2:44:22 PM]
Q3 : For example..


struct MemBlock {
MemBlock *pPrev;
MemBlock *pNext;
unsigned int BlockSize;
unsigned int Pad
};


void free(void *pMem)
{
Memblock *pBlock = (Memblock *)((unsigned int)pMem - sizeof(MemBlock));

AddBlocktoFreeList(pBlock);
}




[edited by - Narcist on November 16, 2003 2:43:33 PM]

This topic is closed to new replies.

Advertisement