Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29258 Discussions

Intel FORTRAN code makes unrepeatable address of VC++ dynamic memory allocation.

chikuma
Beginner
775 Views

My code is mixed with Intel FORTRAN and VC++. One of my Fortran subroutine calls my VC++ subroutine repeatedly. Inside of this VC++ subroutine dynamic memory allocation is taking place. My FORTRAN codes do dynamic allocation as well. What happens is that VC++ new dynamic allocation allocates memory at different addresses for each execution, that makes my code behaves differently each run. As far as stick to VC++ without Intel FORTRAN, VC++ dynamic memory allocation allocate the exact same address each run, but after mixing with Intel FORTRAN, VC++ allocate different addresses for each run. Anybody knows how to avoid this?

Thanks

0 Kudos
5 Replies
Nick2
New Contributor I
775 Views

Correct me if I'm wrong, but by definition, dynamic memory allocation means that you don't know at which address it will be allocated until it is actually allocated...granted, you can achieve allocation at the same offset from the app base address if you do the same program sequence again, but...why is this an issue? If I have

char*szDum=new char[50];

then I know that my memory address is going to be stored in the variable szDum. If I want the memory address of the 0th character in the string, I use &szDum[0] if I want the address of the 1st character, I use &szDum[1] and such...

0 Kudos
chikuma
Beginner
775 Views

You are absolutely right. This is my observation. When I run VC++ without Intel FORTRAN.

For example

VC++ code

double * array1 = new [10];
double * array2 = new [10]
double * array3 = new [10]

cout << array1<< endl;
cout << array2<< endl;
cout << array3<< endl;

output of 1st run

0x0012e0cc
0x01bd4190
0x0012e0a4

output of 2nd run

0x0012e0cc
0x01bd4190
0x0012e0a4

output of 3rd run

0x0012e0cc
0x01bd4190
0x0012e0a4

I observed that VC++ allocates each array at the same address for each execution as shown as above. But this is not true with the code is mixed with Intel FORTRAN.

This case the result will be like this

output of 1st run

0x0022a01c
0x0d1d4190
0x0033e0a4

output of 2nd run

0x0033e0cc
0x02bc5190
0x0032f0a4

output of 3rd run

0x0032e0ca
0x02bd41a0
0x0032e0a5


I observe that the Intel FORTRAN mixed VC++ executable allocates different addresses for each execution.

Answering to your question why do I care about this, what I do is

std::list< double * > pointer_list;

pointer_list.push_back(array1);
pointer_list.push_back(array2);
pointer_list.push_back(array3);
pointer_list.push_back(array1);
pointer_list.push_back(array2);
pointer_list.push_back(array1);

pointer_list.sort();
pointer_list.unique();

The reason I do sort and unique is to remove duplication of pointers. Then my following routine processes objects in sequence of pointer_list using STL iterator. My algorithm has dependency on which one is processed first and next. Then I got different result for each execution. If I eliminate sorting based on pointer address, I can make the executable repeatable. But right now this is the fastest way as far as I know. And I do not want to slow down my code.

I dynamically allocate 1000 of VC++ classes and create duplicated pointer list, that is subset of 1000. (This is coming from nature of my algorithm. Not my intension. ) And then to remove the duplication of objects I sort pointers based on its address.


0 Kudos
Nick2
New Contributor I
775 Views

The only thing I can think of is, if somewhere, some memory is not getting freed; I'm not too sure how Fortran does memory allocation.

When you run only your C++ code without the Fortran, are you running each run as a separate process? In other words, do you do

myapp.exe
myapp.exe
myapp.exe

if so, the reason you're seeing what you're seeing is because you don't free the memory; try this:

double * array1 = new [10];
double * array2 = new [10]
double * array3 = new [10]

cout << array1<< endl;
cout << array2<< endl;
cout << array3<< endl;

delete[]array1;
delete[]array2;
delete[]array3;

Now, if you're trying to sort your data, and notcare too much about where it is in the memory,I'd add a unique ID to each data item, and sort them according to those IDs.

Class MyClass
{
int ID;
double*values;
};

bool operator<(const MyClass& a, const MyClass&b)
{
return a.ID}

And at this point you can do the STL sort. If you want to generate unique IDs, well, shoot, managed code can get you a hash in about 2 lines.

0 Kudos
Steven_L_Intel1
Employee
775 Views
When you say "between each run" do you mean separate runs of the EXE or different "passes" within the same EXE run? Once an EXE exits, everything about memory allocated is forgotten.
0 Kudos
grg99
Beginner
775 Views
You cannot depend on memory allocation addresses having any pattern. There is and never has been any guarantee.

The ALLOCATE and new(0 functions may give you upward-counting addresses for a little while, but as soon as you or the run-time system frees up a block, that block could be given back to you on a later ALLOCATE or new(). And the Fortran run-time system unfortunately does quite a few allocations and deallocations behind your back. Nothing really wrong with that-- lots of string and array operations require temporary storage to do their job.


If you need a sequential allocation counter, just make your array a struct or derived type with a integer field in it, then set this field on each allocation. That's guaranteed to work.





0 Kudos
Reply