In Fortran coding language, what is Deallocate(x) is used for? x variable is an array. I heard it deletes all the elements in it. Is it true?
One of its example:
Toplam = 0.0
DO K = 1, N
Toplam = (Ort - X(K))**2
END DO ! bellek bloğu boşaltılıyor
DEALLOCATE(X)
Std_Sap = SQRT(Toplam/(N-1))
PRINT *,"Ortalama : ",Ort
PRINT *,"Standart sapma: ",Std_Sap END PROGRAM Ortalama
The linked question When is array deallocating necessary? is very closely related and I will try to avoid repeating points raised there and strictly just answer the main point "What does deallocate() actually do"?
Allocatable variables (scalars and arrays) are just handles or references. They do not actually refer to any part of memory untill they are allocated using allocate(). This allocation gives them some part of memory that they occupy. At that moment the status changes from "not allocated" to "allocated". (You can query the status using the allocated() function.)
If you have an allocated allocatable (e.g. allocatable array), you can deallocate it using deallocate(). This deallocation takes the memory back from the variable/array. The variable is now "not allocated" and contains no data elements. It does not have any array size, you cannot read it, write to it, you cannot even print the size() or shape(), it is just "not allocated" - that's all. It does not any longer refer to any particular memory.
You use the word "deleted" in your question. The memory might not be overwritten and the values that had been stored there could remain there. But they no longer belong to that array and the memory may be given to some other allocatable or pointer variable.
As the linked answers show, in some situations the deallocation is performed automatially.
Related
I have array declared in something like this
first way
int size=256*10;
float *array=(float*)malloc(size * sizeof(float));
for(int i=0;i<2398;i++)
data[i]=data[i]*900;
When I used this why in declaration my code run with out errors but
when I use the array as constant values like this :
2nd way
float array[]={120.0, 160.0, 255.0, 216.0, 255.0, 224.0, 0.0, 16.0,
74.0, 70.0, 73.0, 70.0, 0.0, 1.0, 1.0};
I didn't get what was required from the code even if I took the array output in the first way and defined it as in 2nd way?!!
I thought defining an array in the 2nd way is correct and equivalent to the first definition?!
What is the correct way to declare an array that equivalent to the first way?
Both ways create valid arrays, and you can use them pretty much exchangably if you pay attention to object life time. The differences are:
malloc dynamically allocates memory which exists until the program explicitly calls free() on the address returned by malloc. One of the typical use cases is to allocate and initialize some storage in a function and let the function return the address. That's fine: The life time of objects in dynamically allocated memory (new, malloc) is independent of scope (e.g., a function).
By contrast, an array defined the second way exists until the variable goes out of scope. If it is a global variable it will exist until the program ends. If it is defined in a function it will only exist until the program returns from the function, or ends. That may be your problem here. Returning the address of a function-local object and using it outside that function is a not uncommon error. Newer compilers with sufficiently high warning levels should warn when they see such a mistake.
The second array is an object with the number of elements indicated by the initializers, exactly. You can call sizeof(array) and get a large number, for example 60. The first "array", by contrast, is not an array at all: It is a pointer to the first element of an array. Calling sizeof() on that pointer returns the size of that pointer, typically 4 or 8, no matter how much memory is allocated at the location the pointer points to. There is no built-in way to keep track of the size of the allocated memory — the programmer must store it somewhere. Typically, larger programs have a constant or a define somewhere in a header shared by "translation units" (source files) so that parts of the program that use the allocated memory don't overshoot its limits, and the part allocating it knows how much is needed.
Standard C++ doesn't have variable length arrays: Array sizes must be known at compile time. That's obviously not always possible. For example, most image formats contain the image size in the first few bytes of the file. A program reading such an image would read a few bytes into an information structure and then dynamically allocate the needed memory for the actual pixels. If you want to use compile-time sized arrays you can, of course, simply define one that's big enough for large pictures and only use part of it for smaller ones. But you'll end up with array sizes that normally waste space because they are much too large for the average picture — but will probably still not fit the largest picture they may encounter! It is much better to use a data structure whose size can be determined or changed at run time, like a std::vector, or arrays created with new() or, if you must, malloc().
Remarks:
You don't use the entire allocated memory which is a bit strange: You allocate 2560 floats but assign values only to 2398.
The assignment data[i]=data[i]*900; reads from the uninitialized element data[i] before assigning to it. Reading uninitialized memory is verboten and kaput ("undefined behavior"), and the program is faulty. In practice you'll probably simply have funny float values, but still. Don't do it.
If you have an array you want to initialize with a few dozen values known at compile time I'd strongly prefer a true array. If it needs to live longer than the function you can make it static and let the function return a pointer to it.
Only if you need a lot of memory (2500 floats qualifies) or must create an array whose size is unknown at compile time, or must create an unknown number of arrays, consider creating them dynamically.
As others have remarked in comments, real-world code would use a vector or a smart pointer and/or std::array. Explicit dynamic allocation has pretty much become a domain of beginner homework (I'm not condescending: It has its place there) or projects stuck with old compilers (don't ask).
I'm a student taking a class on Data Structures in C++ this semester and I came across something that I don't quite understand tonight. Say I were to create a pointer to an array on the heap:
int* arrayPtr = new int [4];
I can access this array using pointer syntax
int value = *(arrayPtr + index);
But if I were to add another value to the memory position immediately after the end of the space allocated for the array, I would then be able to access it
*(arrayPtr + 4) = 0;
int nextPos = *(arrayPtr + 4);
//the value of nextPos will be 0, or whatever value I previously filled that space with
The position in memory of *(arrayPtr + 4) is past the end of the space allocated for the array. But as far as I understand, the above still would not cause any problems. So aside from it being a requirement of C++, why even give arrays a specific size when declaring them?
When you go past the end of allocated memory, you are actually accessing memory of some other object (or memory that is free right now, but that could change later). So, it will cause you problems. Especially if you'll try to write something to it.
I can access this array using pointer syntax
int value = *(arrayPtr + index);
Yeah, but don't. Use arrayPtr[index]
The position in memory of *(arrayPtr + 4) is past the end of the space allocated for the array. But as far as I understand, the above still would not cause any problems.
You understand wrong. Oh so very wrong. You're invoking undefined behavior and undefined behavior is undefined. It may work for a week, then break one day next week and you'll be left wondering why. If you don't know the collection size in advance use something dynamic like a vector instead of an array.
Yes, in C/C++ you can access memory outside of the space you claim to have allocated. Sometimes. This is what is referred to as undefined behavior.
Basically, you have told the compiler and the memory management system that you want space to store four integers, and the memory management system allocated space for you to store four integers. It gave you a pointer to that space. In the memory manager's internal accounting, those bytes of ram are now occupied, until you call delete[] arrayPtr;.
However, the memory manager has not allocated that next byte for you. You don't have any way of knowing, in general, what that next byte is, or who it belongs to.
In a simple example program like your example, which just allocates a few bytes, and doesn't allocate anything else, chances are, that next byte belongs to your program, and isn't occupied. If that array is the only dynamically allocated memory in your program, then it's probably, maybe safe to run over the end.
But in a more complex program, with multiple dynamic memory allocations and deallocations, especially near the edges of memory pages, you really have no good way of knowing what any bytes outside of the memory you asked for contain. So when you write to bytes outside of the memory you asked for in new you could be writing to basically anything.
This is where undefined behavior comes in. Because you don't know what's in that space you wrote to, you don't know what will happen as a result. Here's some examples of things that could happen:
The memory was not allocated when you wrote to it. In that case, the data is fine, and nothing bad seems to happen. However, if a later memory allocation uses that space, anything you tried to put there will be lost.
The memory was allocated when you wrote to it. In that case, congratulations, you just overwrote some random bytes from some other data structure somewhere else in your program. Imagine replacing a variable somewhere in one of your objects with random data, and consider what that would mean for your program. Maybe a list somewhere else now has the wrong count. Maybe a string now has some random values for the first few characters, or is now empty because you replaced those characters with zeroes.
The array was allocated at the edge of a page, so the next bytes don't belong to your program. The address is outside your program's allocation. In this case, the OS detects you accessing random memory that isn't yours, and terminates your program immediately with SIGSEGV.
Basically, undefined behavior means that you are doing something illegal, but because C/C++ is designed to be fast, the language designers don't include an explicit check to make sure you don't break the rules, like other languages (e.g. Java, C#). They just list the behavior of breaking the rules as undefined, and then the people who make the compilers can have the output be simpler, faster code, since no array bounds checks are made, and if you break the rules, it's your own problem.
So yes, this sometimes works, but don't ever rely on it.
It would not cause any problems in a a purely abstract setting, where you only worry about whether the logic of the algorithm is sound. In that case there's no reason to declare the size of an array at all. However, your computer exists in the physical world, and only has a limited amount of memory. When you're allocating memory, you're asking the operating system to let you use some of the computer's finite memory. If you go beyond that, the operating system should stop you, usually by killing your process/program.
Yes, you must write it as arrayptr[index] because the position in memory of *(arrayptr + 4) is past the end of the space which you have allocated for the array. Its the flaw in C++ that the array size cant be extended once allocated.
I have written a fortran code which is failing in a way that I do not understand. I have tried to explain the scenario clearly below but please ask me to clarify if it is not clear.
The code includes a subroutine
SUBROUTINE TMGP(NSYM,NOB,NFT,DEN,ncod,PR,np,lden,NPMX,nuccen,mdel)
IMPLICIT NONE
...
INTEGER :: NINTS
REAL(KIND=wp), ALLOCATABLE :: XBUF(:)
...
print *,"xbuf allocated ?",allocated(xbuf)
print *,"xbuf not allocated ?",.not.allocated(xbuf)
if (allocated(xbuf)) then
DEALLOCATE(xbuf)
end if
if (.not.allocated(xbuf)) then
allocate (xbuf(nints))
end if
...
RETURN
END SUBROUTINE TMGP
However when I run this program it fails on the line:
DEALLOCATE(xbuf)
With the error
forrtl: severe (173): A pointer passed to DEALLOCATE points to an array that cannot be deallocated
With the output:
xbuf allocated ? T
xbuf not allocated ? F
If I change the code to (and make NO other changes than adding this line):
print *,"xbuf allocated ?",allocated(xbuf)
print *,"xbuf not allocated ?",.not.allocated(xbuf)
print *,"nints = ",nints
if (allocated(xbuf)) then
DEALLOCATE(xbuf)
end if
if (.not.allocated(xbuf)) then
allocate (xbuf(nints))
end if
and run this program it fails on the line:
allocate (xbuf(nints))
and I get the message:
forrtl: severe (151): allocatable array is already allocated
With the output:
xbuf allocated ? F
xbuf not allocated ? T
nints = 1
I am quite baffled by this as it seems to me the if statements I have used should make this kind of issue impossible and following the logic of the code these errors should not be possible.
I am using ifort compiler, any ideas on what could be causing this issue or suggestions on how to fix it would be very much appreciated.
Please let me know if any additional information would be useful.
James
Your observations are a likely consequence of corruption of the internal descriptor that the compiler uses to track the status of an allocatable (or pointer) object, interacting with the way in which that specific compiler stores and tests the allocation status of an object.
This is very much implementation detail for that specific compiler, but there are at least two ways in which the "allocated" status of an object is stored in the descriptor for the object - a non-null machine address for the actual data backing the object, and a separate flag set in the descriptor. The allocated intrinsic is looking at one of these pieces of information, while the runtime support for the ALLOCATE statement is looking at another. Normally these two pieces of information are consistent, but in the face of memory corruption you see the apparent contradiction. Documentation for the layout of the descriptor for the current version of Intel Fortran can be found at https://software.intel.com/en-us/node/525356.
(Another flag tracks whether the descriptor is for something that can be deallocated (i.e. it was something created by ALLOCATE or similar) or not (perhaps the descriptor is for a pointer that references a section of another array) - corruption of that flag results in the "... array cannot be deallocated" message.)
The memory corruption is likely caused by an error in your program, which may not be in the immediate source location of the array declaration and use. As suggested by others in the comments - go looking for programming errors in your code such as array subscripts being out of bounds or mismatches in argument lists. The compiler's runtime diagnostic options often help. With appropriate debugging ability, you can also monitor the memory storage for the relevant array descriptor, and determine exactly when the inconsistency in the state of the descriptor first appears.
What is the advantage of allocating a memory for some data. Instead we could use an array of them.
Like
int *lis;
lis = (int*) malloc ( sizeof( int ) * n );
/* Initialize LIS values for all indexes */
for ( i = 0; i < n; i++ )
lis[i] = 1;
we could have used an ordinary array.
Well I don't understand exactly how malloc works, what is actually does. So explaining them would be more beneficial for me.
And suppose we replace sizeof(int) * n with just n in the above code and then try to store integer values, what problems might i be facing? And is there a way to print the values stored in the variable directly from the memory allocated space, for example here it is lis?
Your question seems to rather compare dynamically allocated C-style arrays with variable-length arrays, which means that this might be what you are looking for: Why aren't variable-length arrays part of the C++ standard?
However the c++ tag yields the ultimate answer: use std::vector object instead.
As long as it is possible, avoid dynamic allocation and responsibility for ugly memory management ~> try to take advantage of objects with automatic storage duration instead. Another interesting reading might be: Understanding the meaning of the term and the concept - RAII (Resource Acquisition is Initialization)
"And suppose we replace sizeof(int) * n with just n in the above code and then try to store integer values, what problems might i be facing?"
- If you still consider n to be the amount of integers that it is possible to store in this array, you will most likely experience undefined behavior.
More fundamentally, I think, apart from the stack vs heap and variable vs constant issues (and apart from the fact that you shouldn't be using malloc() in C++ to begin with), is that a local array ceases to exist when the function exits. If you return a pointer to it, that pointer is going to be useless as soon as the caller receives it, whereas memory dynamically allocated with malloc() or new will still be valid. You couldn't implement a function like strdup() using a local array, for instance, or sensibly implement a linked representation list or tree.
The answer is simple. Local1 arrays are allocated on your stack, which is a small pre-allocated memory for your program. Beyond a couple thousand data, you can't really do much on a stack. For higher amounts of data, you need to allocate memory out of your stack.
This is what malloc does.
malloc allocates a piece of memory as big as you ask it. It returns a pointer to the start of that memory, which could be treated similar to an array. If you write beyond the size of that memory, the result is undefined behavior. This means everything could work alright, or your computer may explode. Most likely though you'd get a segmentation fault error.
Reading values from the memory (for example for printing) is the same as reading from an array. For example printf("%d", list[5]);.
Before C99 (I know the question is tagged C++, but probably you're learning C-compiled-in-C++), there was another reason too. There was no way you could have an array of variable length on the stack. (Even now, variable length arrays on the stack are not so useful, since the stack is small). That's why for variable amount of memory, you needed the malloc function to allocate memory as large as you need, the size of which is determined at runtime.
Another important difference between local arrays, or any local variable for that matter, is the life duration of the object. Local variables are inaccessible as soon as their scope finishes. malloced objects live until they are freed. This is essential in practically all data structures that are not arrays, such as linked-lists, binary search trees (and variants), (most) heaps etc.
An example of malloced objects are FILEs. Once you call fopen, the structure that holds the data related to the opened file is dynamically allocated using malloc and returned as a pointer (FILE *).
1 Note: Non-local arrays (global or static) are allocated before execution, so they can't really have a length determined at runtime.
I assume you are asking what is the purpose of c maloc():
Say you want to take an input from user and now allocate an array of that size:
int n;
scanf("%d",&n);
int arr[n];
This will fail because n is not available at compile time. Here comes malloc()
you may write:
int n;
scanf("%d",&n);
int* arr = malloc(sizeof(int)*n);
Actually malloc() allocate memory dynamically in the heap area
Some older programming environments did not provide malloc or any equivalent functionality at all. If you needed dynamic memory allocation you had to code it yourself on top of gigantic static arrays. This had several drawbacks:
The static array size put a hard upper limit on how much data the program could process at any one time, without being recompiled. If you've ever tried to do something complicated in TeX and got a "capacity exceeded, sorry" message, this is why.
The operating system (such as it was) had to reserve space for the static array all at once, whether or not it would all be used. This phenomenon led to "overcommit", in which the OS pretends to have allocated all the memory you could possibly want, but then kills your process if you actually try to use more than is available. Why would anyone want that? And yet it was hyped as a feature in mid-90s commercial Unix, because it meant that giant FORTRAN simulations that potentially needed far more memory than your dinky little Sun workstation had, could be tested on small instance sizes with no trouble. (Presumably you would run the big instance on a Cray somewhere that actually had enough memory to cope.)
Dynamic memory allocators are hard to implement well. Have a look at the jemalloc paper to get a taste of just how hairy it can be. (If you want automatic garbage collection it gets even more complicated.) This is exactly the sort of thing you want a guru to code once for everyone's benefit.
So nowadays even quite barebones embedded environments give you some sort of dynamic allocator.
However, it is good mental discipline to try to do without. Over-use of dynamic memory leads to inefficiency, of the kind that is often very hard to eliminate after the fact, since it's baked into the architecture. If it seems like the task at hand doesn't need dynamic allocation, perhaps it doesn't.
However however, not using dynamic memory allocation when you really should have can cause its own problems, such as imposing hard upper limits on how long strings can be, or baking nonreentrancy into your API (compare gethostbyname to getaddrinfo).
So you have to think about it carefully.
we could have used an ordinary array
In C++ (this year, at least), arrays have a static size; so creating one from a run-time value:
int lis[n];
is not allowed. Some compilers allow this as a non-standard extension, and it's due to become standard next year; but, for now, if we want a dynamically sized array we have to allocate it dynamically.
In C, that would mean messing around with malloc; but you're asking about C++, so you want
std::vector<int> lis(n, 1);
to allocate an array of size n containing int values initialised to 1.
(If you like, you could allocate the array with new int[n], and remember to free it with delete [] lis when you're finished, and take extra care not to leak if an exception is thrown; but life's too short for that nonsense.)
Well I don't understand exactly how malloc works, what is actually does. So explaining them would be more beneficial for me.
malloc in C and new in C++ allocate persistent memory from the "free store". Unlike memory for local variables, which is released automatically when the variable goes out of scope, this persists until you explicitly release it (free in C, delete in C++). This is necessary if you need the array to outlive the current function call. It's also a good idea if the array is very large: local variables are (typically) stored on a stack, with a limited size. If that overflows, the program will crash or otherwise go wrong. (And, in current standard C++, it's necessary if the size isn't a compile-time constant).
And suppose we replace sizeof(int) * n with just n in the above code and then try to store integer values, what problems might i be facing?
You haven't allocated enough space for n integers; so code that assumes you have will try to access memory beyond the end of the allocated space. This will cause undefined behaviour; a crash if you're lucky, and data corruption if you're unlucky.
And is there a way to print the values stored in the variable directly from the memory allocated space, for example here it is lis?
You mean something like this?
for (i = 0; i < len; ++i) std::cout << lis[i] << '\n';
This is similar to What does zero-sized array allocation do/mean?
I have following code
int *p = new int[0];
delete []p;
p gets an address and gets deleted properly.
My question is: Why allocation of zero bytes is allowed by c++ Standard in the first place?
Why doesn't it throw bad_alloc or some special exception ?
I think, It is just postponing the catastrophic failure, making programmer's life difficult. Because if size to be allocated is calculated at run time and if programmer assumes its allocated properly and tries to write something to that memory, ends up corrupting memory !!! and Crash may happen some where else in the code.
EDIT: How much memory it allocates upon zero size request ?
Why would you want it to fail? If the programmer tries to read/write to non-existent elements, then that is an error. The initial allocation is not (this is no different to e.g. int *p = new int[1]; p[1] = 5;).
3.7.3.1/2:
[32. The intent is to have operator new() implementable by calling malloc() or calloc(), so the rules are substantially the same. C++ differs from C in requiring a zero request to return a non-null pointer.]
Compare dynamically allocated array to std::vector for example. You can have a vector of size 0, so why not allow the same for the array? And it is always an error to access past the end of the array whether its size is 0 or not.
Long time ago, before using exceptions, the malloc function returned a NULL pointer if the allocation failed.
If allocating zero bytes would also return a NULL pointer, it would be hard to make the distinction between a failed allocation and a succeeding-zero-bytes allocation.
On the other hand if the allocation of zero bytes would return a non-NULL pointer, you end up with a situation in which two different allocations of zero bytes can have the same pointer.
Therefore, to keep things simple, the malloc function of zero bytes allocates 1 byte.
The same can be said for int[N] where N>0:
Because if size to be allocated is calculated at run time and if programmer assumes its allocated properly and tries to write something past end of that memory, ends up corrupting memory !!! and Crash may happen some where else in the code.
Zero sized array allocation is covered in the ISO C++ Standard under 5.3.4, paragrahp 7
When the value of the expression in a direct-new-declarator is zero, the allocation function is called to allocate an array with no elements.
This makes code that performs dnaymic array allocation easier.
In general: If someone calls a function and asks it to return an array with n (0 in your case) elements, the code shouldn't be trying to read the returned array past the n-nth element anyway.
So, I don't really see the catastrophic failure, since the code would have been faulty to begin with for any n.
As you say:
Because if size to be allocated is calculated at run time and if programmer assumes its allocated properly
The calculated size would be "0", if he tries to access more than his calculated size then, well.. I am repeating myself ;)