It seems to be a common sense in C/C++ that, the function which new/malloc some memory should delete/free them before the function finishes, right?
But suppose I have this kind of problem that, there is a function reader which will read chunks from a file into buffers, there is another function consumer will consume these buffer latter,
void reader(ifstream &ifs)
{
char *buf = new char[100];
ifs.read(buf, 100);
save_buffer(buf); //save this buf into a global array, say buf_array[10]
}
void consumer()
{
for(int i = 0; i < 10; i++)
consume( buf_array[i] ); //do something with those buffers read by reader
}
My problem is, many memory resources are newed inside reader, but reader cannot delete them, because these buffers haven't been used by consumer. Should consumer be responsible for deleteing those buffers?
No one said the function that allocates memory should free the memory. But generally the same component should handle it. Because your reader and consumer form a pair, it is fine for them to coordinate the memory together.
It seems to be a common sense in C/C++ that, the function which new/malloc some memory should delete/free them before the function finishes, right?
No, this is not necessarily true, you do not have to release memory in the same function, as long as you release it eventually before the program ends.
One common solution available in C++ (but not in C) is to deallocate memory in the destructor. If you pass around objects that contain dynamically allocated memory while dealing correctly with the copy/move constructors and assignment operators, the memory will be released when the destructor is called.
The principle is that "for every new, there should be a delete". That doesn't say anything about both calls having to be within the same function (obviously, that wouldn't be very useful).
There's no problem with your example with the reader allocating and the consumer freeing.
You need not free an allocated buffer in the same function in which you initialized it, as long as you carry around a pointer to the buffer.
In your case, consumer() should be responsible for deleteing the buffers allocated by consumer.
As for your secondary question, consumer doesn't know where the buffer ends; you need to tell it somehow. Instead of just storing pointers to the buffers, you might consider defining a new struct encapsulating both a buffer and its length. This has already been done: consider looking at using std::string.
You are copying the contents of buf to a global array buf_arrray which actually feeds the consumer. So, in the example above reader can free the buf.
And, it is not requrired that the function that new/mallocs should be freeing up the memory. The pointer can be passed around. The function that last uses the memory allocated needs to free it the memory.
You don't have to do new/malloc(allocation) and delete/free(release) in the same function. As long as your algorithm guarantees that every allocation does get released and only gets released once, so that it does not cause memory-leak, it is fine.
In fact, often the allocation and release do exist in separate functions.
Just remember these:
1. Use the same pointer to do the release(you can pass the pointer around of course). If you do some arithmetic on the pointer and then release the allocation using that modified pointer, it would produce an error even the pointer still points in the allocation region.
2. As mentioned above, you should guarantee that the allocation got released, and only once. Additional release causes an error.
Slightly different answer to everyone else:
Yes it is fine for the Reader not to free/delete the memory in the reading function, but I wouldn't have the consumer delete the memory. In a simple case works, but what if you have multiple consumers (e.g. to output in different formats)? If consuming the data has the side effect of freeing it, then you cannot do anything else with the data after the fist consumer does it's thing.
I would have a cleanup() type method in my reader that I explicitly call to cleanup the buffers when required. This way the module that allocates the memory is responsible for freeing it (even though it is in a different method).
e.g.
Data d = Reader.read();
Consumer1.consume(d);
Consumer2.consume(d);
Reader.cleanup(d);
// d is no longer valid.
You could also read about shared arrays http://www.boost.org/doc/libs/1_35_0/libs/smart_ptr/shared_array.htm
Using shared arrays, you can allocate them inside a function and pass them by value to other functions. The shared array keeps an internal count of how many times it has been referenced, and deletes the memory automagically when all references have gone out of scope.
eg
void bar( boost::shared_array< int > );
void foo()
{
boost::shared_array< int > x ( new int[ 100 ] );
bar( x );
// because x has been passed to bar(), its reference count is incremented
// and it will not only be deleted when everyone is finished with it!
// do more things with x
} // the memory held by x is deleted
void bar( boost::shared_array< int > y )
{
// Do things with y here
} // the memory held by y is not deleted here because foo() hasn't yet finished
In descending order of preference you'd prefer to:
Use auto storage class, so deletion happens automatically.
Have the same same code allocate and delete objects.
Pass ownership, so one component allocates and another frees.
Have shared ownership via something like shared_ptr.
3 and 4 are nearly tied, but both are quite a ways behind 2, which is quite a ways behind 1.
In this case, what you'd really prefer is for the level of function (or class, etc.) above both the producer and consumer to allocate the buffers, start the producer and consumer, and delete the buffers when both are finished:
class buffer {
std::vector<char> data;
public:
buffer() : data(100) {}
};
process_file(std::string const &name) {
std::vector<buffer> buffers(10);
std::ifstream in(name);
std::pair<std::ifstream *, std::vector<buffer> *> thread_data = {
&in, &buffers
};
prod = start_thread(producer, (void *)&thread_data);
cons = start_thread(consumer);
join(prod);
join(cons);
}
If you can do this, it can help avoid a lot of headaches in managing the memory.
Related
I was thinking about a this situation not for a real implementation but to understand better how pointers works.
class foo(){
foo();
~foo();
void doComplexThings(const std::vector<int*>& v){
int* copy;
for(int i = 0; i < v.size(); i++){
copy = v[i];
// do some stuffs
}
}
}
main(){
std::vector<int*> myVector; // suppose we have 100 elements
doComplexThings(myVector);
for(int i = 0; i < myVector.size(); i++){
delete myVector[i];
}
myVector.clear();
}
Ok, I know that have no sense to copy v[i] inside an other pointer, but I was thinking: copy do a memory leak?
After the execution of doComplexThings(), copy will continue to exist and will occupy space in the heap?
After deleting all elements it will continue to exist and point to a deallocated memory?
So logically if I do this things with complex objects I'll keep occupy the memory with unreference object? Or copy is saved in the stack because I don't use new? And at the end of doComplexThings it will be deleted?
I'm a bit confused, thanks!
There is some confusion on the topic of pointers in the C++ community. While it is true that smart pointers have been added to the library to alleviate problems with dynamic memory allocation, raw pointers are not obsolete. In fact, whenever you want to inspect another object without owning it, you should use a reference or raw pointer, depending on which suits your needs. If the concept of ownership is unclear to you, think of an object as being owned by another object if the latter is responsible for cleaning up afterwards (deleting the former).
For example most uses of new and delete should be replaces with the following (omitting std for brevity):
{
auto ptr_to_T = make_unique<T>(//constructor params);
do_stuff_with_smart_ptr(ptr_to_T);
do_stuff_with_T(*ptr_to_T);
do_stuff_with_raw_ptr(ptr_to_T.get());
} // automatic release of memory allocated with make_unique()
Notice how a function that takes a T* doesn't need a smart pointer if it doesn't keep a copy of the T* it is given, because it doesn't affect the lifetime of the object. The object is guaranteed to be alive past the return point of do_stuff_with_T() and its function signature signals that it doesn't own the object by taking a raw pointer.
On the other hand, if you need to pass the pointer to an object that is allowed to keep the pointer and reference it later, it is unclear when the object will need to be destroyed and most importantly by whom. This is solved via a shared pointer.
ClassThatNeedsSharedOwnership shared_owner;
{
auto ptr_to_T = make_shared<T>(//constructor params);
shared_owner.set_T(ptr_to_T);
// do a lot of stuff
}
// At this point ptr_to_T is destroyed, but shared_owner might keep the object alive
So how does the above factor in to your code. First of all, if the vector is supposed to own (keep alive) the ints it points to, it needs to hold unique_ptr<int> or shared_ptr<int>. If it is just pointing to ints held by something else, and they are guaranteed to be alive until after the vector is destroyed, you are fine with int*. In this case, it should be evident that a delete is never necessary, because by definition your vector and the function working on the vector are not responsible for cleaning-up!
Finally, you can make your code more readable by changing the loop to this (C++11 which you've tagged in the post):
for (auto copy : v){
// equivalent to your i-indexed loop with copy = v[i];
// as long as you don't need the value of i
do_stuff_to_int_ptr(copy);
// no delete, we don't own the pointee
}
Again this is only true if some other object holds the ints and releases them, or they are on the stack but guaranteed to be alive for the whole lifetime of vector<int*> that points to them.
No additional memory is allocated on the heap when you do this:
copy = v[i];
variable copy points to the same address as v[i], but no additional array is allocated, so there would be no memory leak.
A better way of dealing with the situation is to avoid raw pointers in favor of C++ smart pointers or containers:
std::vector<std::vector<int>> myVector;
Now you can remove the deletion loop, which is an incorrect way of doing it for arrays allocated with new int[length] - it should use delete[] instead:
delete[] myVector[i];
Basically you're illustrating the problem with C pointers which lead to the introduction of C++ unique and shared pointers. If you pass a vector of allocated pointers to an opaque member function, you've no way of knowing whether that function hangs onto them or not, so you don't know whether to delete the pointer. In fact in your example you don't seem to, "copy" goes out of scope.
The real answer is that you should only seldom use allocated pointers in C++ at all. The stl vector will serve as a safer, easier to use version of malloc / new. Then you should pass them about as const & to prevent functions from changing them. If you do need an allocated pointer, make one unique_ptr() and then you know that the unique_ptr() is the "owner" of the memory.
always delete pointer even if it is just in function call stack?
Isn't it disappeared when function stack released?
// just Simple class
class CSimple{
int a;
}
// just simple function having pointer.
void simpleFunc(){
CSimple* cSimple = new CSimple();
cSimple->a = 10;
//.. do sth
delete cSimple; // <<< Always, do I have to delete 'cSimple' to prevent the leak of memory?
}
void main(){
for( int =0 ; i< 10 ; i++){
simpleFunc();
}
}
when function stack released?
It is true that "CSimple *csimple" goes away when the function returns.
However, there's a big difference between the pointer, and what it's pointed to.
When a pointer object gets destroyed, nothing happens to whatever the pointer is pointing to. There isn't just one, but two objects here:
The pointer.
What it's pointing to.
In this case, the pointer is pointing to an object in dynamic scope that was created with new.
Nothing is going to happen to this object, otherwise, so you will leak memory.
Therefore, this object needs to be deleted.
After you understand, and fully wrap your brain around this concept, your next step will be to open your C++ book to the chapter that talks about the std::unique_ptr and std::shared_ptr classes, which will take care of these pesky details, for you. You should learn how to use them. Modern C++ code rarely needs to delete something; rather these smart pointers do all the work.
Yes.
On scope exit (ex. when function exists or block { ... } finishes), all objects created on stack will be destroyed and memory will be freed.
This applies to your case, ie. the pointer will be destroyed and memory occupied by the pointer will be freed. The object pointed by the pointer will not be cleared.
This is a common problem and a nightmare when you deal with multiple flow paths (if-else ladders, many return statements) and exceptions.
To solve this problem, we employ 2 main strategies:
RAII
Smart pointers (std::unique_ptr, boost::scoped_ptr, legacy std::auto_ptr, etc).
RAII - without academic consideration - is just creating object on stack, like this:
{
std::string s;
fancy_object obj;
}
When we exit he scope, obj and s destructors will be called duing stack unwinding. Compiler ensures this for all flow paths and will keep proper order of deallocations for us.
If you need to allocate memory on heap, using new, use a smart pointer.
int foo()
{
std::unique_ptr<Object> o(new Object);
... some more code ...
if( something ) { return -1 }
... some more code ...
if( something_else ) { return -2 }
else { not yet }
return 0;
}
As you can see, we can leave the scope using 3 "exists". Normally, you'd need to clear your memory in all cases, which is prone to human errors.
Instead of clearing the object manually in all 3 palces, we rely on automatic destructor call for objects created on stack. Compiler will figure it out. When we leave the scope, std::unique_ptr destructor will be called, calling delete on Object.
Don't be affraid of smart poiners. They are not "slow", "bloat" or other nonsense. Smart poiners are designed to have no overhead on access, adding extra security.
Very similar technique is used for locks. Check out std::lock_guard class.
Yes, you must delete the data that is being pointed to.
The pointer itself is on the stack and does not need to be deleten.
You can, however, store cSimple on the stack, then you don't have to delete it:
void simpleFunc(){
CSimple cSimple; // no new
cSimple.a = 10; // "." instead of "->"
//.. do sth
// no deletion
}
I'm dynamically creating threads:
auto thr =new std::future<void>(std::async(/*some callable*/));
I'm storing all of these pointers in a std::vector<future<void>*>. For freeing up memory I'm doing like:
for(int i(0);i<futureVector.size();i++)
{
if(futureVector.at(i)->valid())
{
futureVector.at(i)->get(); // for getting exception,if any
}
delete futureVector.at(i); // the problem is here
}
Now in my code it may happen that the memory allocated for futureVector.at(i) is already freed (maybe in some other thread, may beby some other function).
My question is how I can detect the pointer at futureVector.at(i) is valid or not? I'mean it points to a valid std::future or not?
Note: the futureVector variable is static member of my class.
Say if I don't delete that future object is the cost very large ( already retrieved future)
If for some reason you actually need pointers you should not use owning raw pointers in your vector.
auto thr = std::make_unique<std::future<void>>(std::async(/*some callable*/)); // C++14
std::unique_ptr<std::future<void>> thr {new auto {std::async(/*some callable*/)}; // C++11
But really you probably don't need pointers at all. Just because you don't know how many threads you'll create doesn't mean you need to use pointers.
std::vector<std::future<void>> futureVector;
futureVector.emplace_back(std::async(/*some callable*/));
Either way you don't need to loop through manually and delete anything.
(maybe in some other thread, may beby some other function)
If you still go for raw pointers then you really need to define the ownership policy better than that. Allowing some random other bit of code to delete resources it doesn't own is not a good idea.
Basic Question: when does a program call a class' destructor method in C++? I have been told that it is called whenever an object goes out of scope or is subjected to a delete
More specific questions:
1) If the object is created via a pointer and that pointer is later deleted or given a new address to point to, does the object that it was pointing to call its destructor (assuming nothing else is pointing to it)?
2) Following up on question 1, what defines when an object goes out of scope (not regarding to when an object leaves a given {block}). So, in other words, when is a destructor called on an object in a linked list?
3) Would you ever want to call a destructor manually?
1) If the object is created via a pointer and that pointer is later deleted or given a new address to point to, does the object that it was pointing to call its destructor (assuming nothing else is pointing to it)?
It depends on the type of pointers. For example, smart pointers often delete their objects when they are deleted. Ordinary pointers do not. The same is true when a pointer is made to point to a different object. Some smart pointers will destroy the old object, or will destroy it if it has no more references. Ordinary pointers have no such smarts. They just hold an address and allow you to perform operations on the objects they point to by specifically doing so.
2) Following up on question 1, what defines when an object goes out of scope (not regarding to when an object leaves a given {block}). So, in other words, when is a destructor called on an object in a linked list?
That's up to the implementation of the linked list. Typical collections destroy all their contained objects when they are destroyed.
So, a linked list of pointers would typically destroy the pointers but not the objects they point to. (Which may be correct. They may be references by other pointers.) A linked list specifically designed to contain pointers, however, might delete the objects on its own destruction.
A linked list of smart pointers could automatically delete the objects when the pointers are deleted, or do so if they had no more references. It's all up to you to pick the pieces that do what you want.
3) Would you ever want to call a destructor manually?
Sure. One example would be if you want to replace an object with another object of the same type but don't want to free memory just to allocate it again. You can destroy the old object in place and construct a new one in place. (However, generally this is a bad idea.)
// pointer is destroyed because it goes out of scope,
// but not the object it pointed to. memory leak
if (1) {
Foo *myfoo = new Foo("foo");
}
// pointer is destroyed because it goes out of scope,
// object it points to is deleted. no memory leak
if(1) {
Foo *myfoo = new Foo("foo");
delete myfoo;
}
// no memory leak, object goes out of scope
if(1) {
Foo myfoo("foo");
}
Others have already addressed the other issues, so I'll just look at one point: do you ever want to manually delete an object.
The answer is yes. #DavidSchwartz gave one example, but it's a fairly unusual one. I'll give an example that's under the hood of what a lot of C++ programmers use all the time: std::vector (and std::deque, though it's not used quite as much).
As most people know, std::vector will allocate a larger block of memory when/if you add more items than its current allocation can hold. When it does this, however, it has a block of memory that's capable of holding more objects than are currently in the vector.
To manage that, what vector does under the covers is allocate raw memory via the Allocator object (which, unless you specify otherwise, means it uses ::operator new). Then, when you use (for example) push_back to add an item to the vector, internally the vector uses a placement new to create an item in the (previously) unused part of its memory space.
Now, what happens when/if you erase an item from the vector? It can't just use delete -- that would release its entire block of memory; it needs to destroy one object in that memory without destroying any others, or releasing any of the block of memory it controls (for example, if you erase 5 items from a vector, then immediately push_back 5 more items, it's guaranteed that the vector will not reallocate memory when you do so.
To do that, the vector directly destroys the objects in the memory by explicitly calling the destructor, not by using delete.
If, perchance, somebody else were to write a container using contiguous storage roughly like a vector does (or some variant of that, like std::deque really does), you'd almost certainly want to use the same technique.
Just for example, let's consider how you might write code for a circular ring-buffer.
#ifndef CBUFFER_H_INC
#define CBUFFER_H_INC
template <class T>
class circular_buffer {
T *data;
unsigned read_pos;
unsigned write_pos;
unsigned in_use;
const unsigned capacity;
public:
circular_buffer(unsigned size) :
data((T *)operator new(size * sizeof(T))),
read_pos(0),
write_pos(0),
in_use(0),
capacity(size)
{}
void push(T const &t) {
// ensure there's room in buffer:
if (in_use == capacity)
pop();
// construct copy of object in-place into buffer
new(&data[write_pos++]) T(t);
// keep pointer in bounds.
write_pos %= capacity;
++in_use;
}
// return oldest object in queue:
T front() {
return data[read_pos];
}
// remove oldest object from queue:
void pop() {
// destroy the object:
data[read_pos++].~T();
// keep pointer in bounds.
read_pos %= capacity;
--in_use;
}
~circular_buffer() {
// first destroy any content
while (in_use != 0)
pop();
// then release the buffer.
operator delete(data);
}
};
#endif
Unlike the standard containers, this uses operator new and operator delete directly. For real use, you probably do want to use an allocator class, but for the moment it would do more to distract than contribute (IMO, anyway).
When you create an object with new, you are responsible for calling delete. When you create an object with make_shared, the resulting shared_ptr is responsible for keeping count and calling delete when the use count goes to zero.
Going out of scope does mean leaving a block. This is when the destructor is called, assuming that the object was not allocated with new (i.e. it is a stack object).
About the only time when you need to call a destructor explicitly is when you allocate the object with a placement new.
1) Objects are not created 'via pointers'. There is a pointer that is assigned to any object you 'new'. Assuming this is what you mean, if you call 'delete' on the pointer, it will actually delete (and call the destructor on) the object the pointer dereferences. If you assign the pointer to another object there will be a memory leak; nothing in C++ will collect your garbage for you.
2) These are two separate questions. A variable goes out of scope when the stack frame it's declared in is popped off the stack. Usually this is when you leave a block. Objects in a heap never go out of scope, though their pointers on the stack may. Nothing in particular guarantees that a destructor of an object in a linked list will be called.
3) Not really. There may be Deep Magic that would suggest otherwise, but typically you want to match up your 'new' keywords with your 'delete' keywords, and put everything in your destructor necessary to make sure it properly cleans itself up. If you don't do this, be sure to comment the destructor with specific instructions to anyone using the class on how they should clean up that object's resources manually.
Pointers -- Regular pointers don't support RAII. Without an explicit delete, there will be garbage. Fortunately C++ has auto pointers that handle this for you!
Scope -- Think of when a variable becomes invisible to your program. Usually this is at the end of {block}, as you point out.
Manual destruction -- Never attempt this. Just let scope and RAII do the magic for you.
To give a detailed answer to question 3: yes, there are (rare) occasions when you might call the destructor explicitly, in particular as the counterpart to a placement new, as dasblinkenlight observes.
To give a concrete example of this:
#include <iostream>
#include <new>
struct Foo
{
Foo(int i_) : i(i_) {}
int i;
};
int main()
{
// Allocate a chunk of memory large enough to hold 5 Foo objects.
int n = 5;
char *chunk = static_cast<char*>(::operator new(sizeof(Foo) * n));
// Use placement new to construct Foo instances at the right places in the chunk.
for(int i=0; i<n; ++i)
{
new (chunk + i*sizeof(Foo)) Foo(i);
}
// Output the contents of each Foo instance and use an explicit destructor call to destroy it.
for(int i=0; i<n; ++i)
{
Foo *foo = reinterpret_cast<Foo*>(chunk + i*sizeof(Foo));
std::cout << foo->i << '\n';
foo->~Foo();
}
// Deallocate the original chunk of memory.
::operator delete(chunk);
return 0;
}
The purpose of this kind of thing is to decouple memory allocation from object construction.
Remember that Constructor of an object is called immediately after the memory is allocated for that object and whereas the destructor is called just before deallocating the memory of that object.
Whenever you use "new", that is, attach an address to a pointer, or to say, you claim space on the heap, you need to "delete" it.
1.yes, when you delete something, the destructor is called.
2.When the destructor of the linked list is called, it's objects' destructor is called. But if they are pointers, you need to delete them manually.
3.when the space is claimed by "new".
Yes, a destructor (a.k.a. dtor) is called when an object goes out of scope if it is on the stack or when you call delete on a pointer to an object.
If the pointer is deleted via delete then the dtor will be called. If you reassign the pointer without calling delete first, you will get a memory leak because the object still exists in memory somewhere. In the latter instance, the dtor is not called.
A good linked list implementation will call the dtor of all objects in the list when the list is being destroyed (because you either called some method to destory it or it went out of scope itself). This is implementation dependent.
I doubt it, but I wouldn't be surprised if there is some odd circumstance out there.
If the object is created not via a pointer(for example,A a1 = A();),the destructor is called when the object is destructed, always when the function where the object lies is finished.for example:
void func()
{
...
A a1 = A();
...
}//finish
the destructor is called when code is execused to line "finish".
If the object is created via a pointer(for example,A * a2 = new A();),the destructor is called when the pointer is deleted(delete a2;).If the point is not deleted by user explictly or given a new address before deleting it, the memory leak is occured. That is a bug.
In a linked list, if we use std::list<>, we needn't care about the desctructor or memory leak because std::list<> has finished all of these for us. In a linked list written by ourselves, we should write the desctructor and delete the pointer explictly.Otherwise, it will cause memory leak.
We rarely call a destructor manually. It is a function providing for the system.
Sorry for my poor English!
I am working in C++ and have been using pointers a lot lately. I found that there are a few ways to initialize the chunks of memory that I need to use.
void functioncall(int* i)
{
*i = *i + 1;
}
int main(){
int* a = (int*)malloc(sizeof(int));
int az = 0;
functioncall(a);
functioncall(&az);
}
Notice that the first variable int* a is declared as a pointer and then I malloc the memory for it. But, with az it is not a pointer but when calling the function I get the address of the memory.
So, my question is: is there a preferred way =, or is there any penalties one over the other?
int* a = (int*)malloc(sizeof(int));
This allocates memory on the heap. You have to deallocate it on your own, or you'll run into memory leaks. You deallocate it by calling free(a);. This option is most definitely slower (since the memory has to be requested and some other background stuff has to be done) but the memory may be available as long as you call free.
int az = 0;
This "allocates" memory on the stack, which means it gets automatically destroyed when you leave the function it is declared (unless for some really rare exceptions). You do not have to tidy up the memory. This option is faster, but you do not have control over when the object gets destroyed.
a is put onto the heap, az is on the stack. The heap you are responsible to freeing the memory. With the stack when it goes out of scope it is automatically free. So the answer is when you want the data to be placed and if you require if at the end of the scope.
PS You should use new in C++
In general you should avoid dynamic memory allocations (malloc, calloc, new) when it's reasonably easy: they are slower than stack allocations, but, more importantly, you must remember to free (free, delete) manually the memory obtained with dynamic allocation, otherwise you have memory leaks (as happens in your code).
I'm not sure what you're trying to do, but there is almost never a
reason for allocating a single int (nor an array of int, for that
matter). And there are at least two errors in your functioncall:
first, it fails to check for a null pointer (if the pointer can't be
null, pass by reference), and second, it doesn't do anything: it
increments the copy of the pointer passed as an argument, and then
dereferences the initial value and throws out the value read.
Allocating small variables directly on the stack is generally faster since you don't have to do any heap operations. There's also less chance of pointer-related screwups (e.g., double frees). Finally, you're using less space. Heap overheads aside, you're still moving a pointer and an int around.
The first line (int* a = ...) is called dynamically-allocated variable, it is usually used if you don't know before the runtime that how much variables you needed, or if you need it at all.
The second line (int az = 0) is called automatic variable, it is used more regularly.
int az = 0;
functioncall(a);
This is okay, as far as behavior is concerned.
int* a = (int*)malloc(sizeof(int));
functioncall(&az);
This invokes undefined-behaviour (UB), inside the function, when you do *i++. Because malloc only allocates the memory, it does not initialize it. That means, *i is still uninitialized, and reading an uninitialized memory invokes UB; that explains why *i++ is UB. And UB, if you know, is the most dangerous thing in C++, for it means, anything can happen.
As for the original question, what would you prefer? So the answer is, prefer automatic variable over pointer (be it allocated with malloc or new).
Automatic means Fast, Clean and Safe.
func(typename* p)
pointer is call value
*p++ is *p and p++
if change this pointer , not change original.