15 мая 2023 года "Исходники.РУ" отмечают своё 23-летие!
Поздравляем всех причастных и неравнодушных с этим событием!
И огромное спасибо всем, кто был и остаётся с нами все эти годы!

Главная Форум Журнал Wiki DRKB Discuz!ML Помощь проекту


Memory fragmentation & garbage collection

Amir Shoval -- amirs@ncc.co.il
Monday, March 31, 1997

Environment: Win 95, VC4.2b

Hello,

I've written a kind of network monitoring application. This application
should
be active for a long time, so I wanted to check that I'm not consuming a
lot
of memory over time.

I'm quite sure I have the right delete for every new, and that the
delete occurs
not too long after the new. My question can be separated into two:

1) Can memory fragmentation (because of many 'new's and 'delete's of
relatively small objects) cause consuming a lot of memory?

2) If the answer to the above is YES, I know how to prevent
fragmentation 
caused by objects created from my classes, but what about objects
created
from MFC classes? For example CString: It's variable part (actually the
string)
is allocated on the default heap, so if I have many CString objects,
they
probably increase fragmentation. How can I handle this situation?

Any other general advise about memory fragmentation & garbage collecting
would be appreciated.

	10x,
		Amir




Daniel W. Levi -- DLevi@hworks.com
Tuesday, April 01, 1997

[Mini-digest: 2 responses]

Amir,

Yes, programs that run a long time can fragment memory badly, and this will
affect the performance eventually.  Figuring out the actual impact can be
very difficult.

If you can use STL (the standard template library), it will help avoid
fragmentation.  It uses some really slick memory allocation techniques.  

I think CString tries to avoid fragmentation also, by using minimum string
sizes and extending strings by a fixed amount when they need to grow.  I'm
not sure how well it works.

Here's a trick: try to make all the structures you new/delete the same
size, so memory returned to the heap is always the right size.  Of course,
this is rarely possible.

Another trick is to use the stack whenever possible, i.e. use

func()
{
	someclass a;
	...
}

instead of

func()
{
	someclass *a = new someclass;
	...
	// allocate something here that lives beyond the function
	...
	delete a;
}




Question for everybody in general: is there heap analysis tool that will
check fragmentation of the heap?

Dan Levi
dlevi@hworks.com

----------
> From: Amir Shoval 
> To: 'MFC list' 
> Subject: Memory fragmentation & garbage collection
> Date: Monday, March 31, 1997 12:33 AM
> 
> Environment: Win 95, VC4.2b
> 
> Hello,
> 
> I've written a kind of network monitoring application. This application
> should
> be active for a long time, so I wanted to check that I'm not consuming a
> lot
> of memory over time.
> 
> I'm quite sure I have the right delete for every new, and that the
> delete occurs
> not too long after the new. My question can be separated into two:
> 
> 1) Can memory fragmentation (because of many 'new's and 'delete's of
> relatively small objects) cause consuming a lot of memory?
> 
> 2) If the answer to the above is YES, I know how to prevent
> fragmentation 
> caused by objects created from my classes, but what about objects
> created
> from MFC classes? For example CString: It's variable part (actually the
> string)
> is allocated on the default heap, so if I have many CString objects,
> they
> probably increase fragmentation. How can I handle this situation?
> 
> Any other general advise about memory fragmentation & garbage collecting
> would be appreciated.
> 
> 	10x,
> 		Amir
-----From: "Poul A. Costinsky" 

> From: Amir Shoval 
> Environment: Win 95, VC4.2b
> Hello,
> 1) Can memory fragmentation (because of many 'new's and 'delete's of
> relatively small objects) cause consuming a lot of memory?

Not only it can, but very probably will.

> 2) If the answer to the above is YES, I know how to prevent fragmentation

> caused by objects created from my classes, but what about objects
> created from MFC classes? 
> For example CString: It's variable part (actually the string)
> is allocated on the default heap, so if I have many CString objects,
> they probably increase fragmentation. How can I handle this situation?

If you know how to fight a fragmentation -:), the answer is simple:
don't use CStrings in your long-term objects. You should also call
defragmentation
routines sometimes.

> Any other general advise about memory fragmentation & garbage collecting
> would be appreciated.

In Win 95 you can use local memory heaps: one for each size of the object
or category of the classes. Look at my home page for more details.

> 10x,
B'vakasha.
----------

Hope this helps.
Regards,
Poul.
  ("`-''-/").___..--''"`-._     ~~~~~~~~~~Poul A. Costinsky~~~~~~~~~~
    (`6_ 6  )   `-.  (     ).`-.__.`)     Poul@wizsoft.com.NOSPAM.PLEASE
     (_Y_.)'  ._   )  `._ `. ``-..-'
   _..`--'_..-_/  /--'_.' ,'
  (il).-''  (li).'  ((!.-    http://www.wizsoft.com/~Poul
==========Disclaimer:All my words are my own.==========






Barry Tannenbaum -- barry@dddv.com
Tuesday, April 01, 1997

At 08:33 AM 3/31/1997 +0300, you wrote:

> Environment: Win 95, VC4.2b
>
> I've written a kind of network monitoring application. This application should
> be active for a long time, so I wanted to check that I'm not consuming a lot
> of memory over time.
> 
> I'm quite sure I have the right delete for every new, and that the delete
occurs
> not too long after the new. My question can be separated into two:
>
> 1) Can memory fragmentation (because of many 'new's and 'delete's of
relatively > small objects) cause consuming a lot of memory?

Of course.  But unless you've got a pathalogical case, it should tend to
stabilize over time.  There used to be a requirement that you call
_heapmin() to coalese memory, but that seems to have gone away with MSVC
4.0.  Check out the documentation on free().

> 2) If the answer to the above is YES, I know how to prevent fragmentation 
> caused by objects created from my classes, but what about objects created
> from MFC classes? For example CString: It's variable part (actually the
string)
> is allocated on the default heap, so if I have many CString objects, they
> probably increase fragmentation. How can I handle this situation?

If you use your own heaps for your classes and reserve the default heap for
CString, you'll probably minimize fragmentation.

        - Barry

--------------------------------------------------------------------------------

3DV Technology, Inc              Phone: (603) 595-2200 X228
410 Amherst St., Suite 150       Fax:   (603) 595-2228
Nashua, NH  03063                Net:   barry@dddv.com





Mike Blaszczak -- mikeblas@nwlink.com
Tuesday, April 01, 1997

[Mini-digest: 3 responses]

At 11:28 4/1/97 -0500, Daniel W. Levi wrote:

>If you can use STL (the standard template library), it will help avoid
>fragmentation.  It uses some really slick memory allocation techniques.  

The UnStandard Class Library defines behaviour, not an implementation.  As
such, there's no way to make a blanket claim that "[the STL] uses some
really slick memory allocation techniques".

The UnStadard Class Library _does_ dictate that most classes in the library
are templatized around allocators, hwich allows you to implement and specify
your own special-case memory management routines.  If you can craft an
algorithm that is closely optimized to your access patterns and data, you
can increase your application's efficiency.

As-is, though, the UnStandard Class Library implementation that ships with 
VC++ 5.0 and the one that ships with VC++ 4.2 both end up simply calling
the regular C Runtime library implementations of operator new() and operator
delete()--which are pretty good for the general case and have some
optimizations for small block allocations.

But it's pretty easy to see that the UnStandard Class Library implementations
that Microsoft ships aren't doing anything slick at all: they're just calling
the runtime routines.  Quite the opposite is true, in my experience: the
VC++ 5.0 implementation of some of the string stream classes, for example,
are miserably inefficient when it comes to memory management.

Maybe if you buy a different UnStandard Class Library implementation, like
Rogue Wave's, you can find some other behaviour.  But that just goes to 
underscore the fact that the UnStandard specifies behaviour, not an
implementation.

>I think CString tries to avoid fragmentation also, by using minimum string
>sizes and extending strings by a fixed amount when they need to grow.  I'm
>not sure how well it works.

CString uses minimum string sizes, but does not extend strings by a fixed
amount when they need to grow; it just extends them by the amount that they
need to grow.  It's really not doing anything any differently than the
basic_string implementation in the Unstandard Class Library that ships with
VC++ 5.0, for example. (So, I guess if you think the USCL is slick, you'll
necessarily think that CString is slick, since they're doin' the same thing.)

>Here's a trick: try to make all the structures you new/delete the same
>size, so memory returned to the heap is always the right size.  Of course,
>this is rarely possible.

In fact, in an MFC application, it's nearly never possible.  MFC is 
doing its own allocations and deallocations, which means that your efforts
are for naught.  MFC will end up allocating and freeing temporary objects,
or collection marker objects, or a buffer for an API call, and that'll
disrupt your scheme.

>Question for everybody in general: is there heap analysis tool that will
>check fragmentation of the heap?

You can write your own using the _heapwalk() function provided by the CRTL.

I think heap fragmentation is really not worth worrying about, though, aside
from a very few specific (and pretty esoteric) cases. If you're worried about
some objects being allocated and freed very quickly, your best bet is to
override operator new() and operator delete() for the class that implements 
those objects.

Without hearing any details of Amir's application, it's hard to tell if he's
having problems with fragmentation or not: this might be a wild goose chase.

As Poul points out, you can call _heapmin().  But there's no real reason to
avoid CString (or favor basic_string, or avoid basic_string); it's not going
to fragment memory any more heavily than dynamically allocating your own
array of TCHARs if the string content isn't changing a lot.  If it the
content _is_ changing heavily, the effects of CString's reallocations can
be minimized by preallocation while the effects of basic_string's can be
minimized by replacing the allocator implementation.

>In Win 95 you can use local memory heaps: one for each size of the object
>or category of the classes. Look at my home page for more details.

Actually, private heaps are available under WinNT, as well.  They're not
unique to Windows 95.


.B ekiM
  Crotch Rocket   / Full-Body Rocket / Trip Report Central!
95 Honda VFR-750F /   94 Mazda RX-7  / http://www.nwlink.com/~mikeblas/
                 Less work, more hockey!
  These words are my own - I do not speak on behalf of Microsoft.
-----From: Amir Shoval 

To continue the discussion, I am using fixed heaps for 3 of my classes
which
are allocated (and freed) dynamically in large quantities.=20
The second answer talks about 'defragmentation routines'. What are
these?
Can I defragment the default heap somehow?
>From both answers it seems MFC is NOT suitable for writing a
continuously
running application. Is it true (Mike B.)?
Where can I find MFC related 'tips & tricks' for better memory
management?

	10x again,
			Amir

>----------
>From: 	Daniel W. Levi[SMTP:DLevi@hworks.com]
>Sent: 	=E9=E5=ED =F9=EC=E9=F9=E9 01 =E0=F4=F8=E9=EC 1997 19:28
>To: 	mfc-l@netcom.com
>Subject: 	Re: Memory fragmentation & garbage collection
>
>[Mini-digest: 2 responses]
>
>Amir,
>
>Yes, programs that run a long time can fragment memory badly, and this =
will
>affect the performance eventually.  Figuring out the actual impact can =
be
>very difficult.
>
>If you can use STL (the standard template library), it will help avoid
>fragmentation.  It uses some really slick memory allocation techniques. =
=20
>
>I think CString tries to avoid fragmentation also, by using minimum =
string
>sizes and extending strings by a fixed amount when they need to grow.  =
I'm
>not sure how well it works.
>
>Here's a trick: try to make all the structures you new/delete the same
>size, so memory returned to the heap is always the right size.  Of =
course,
>this is rarely possible.
>
>Another trick is to use the stack whenever possible, i.e. use
>
>func()
>{
>	someclass a;
>	...
>}
>
>instead of
>
>func()
>{
>	someclass *a =3D new someclass;
>	...
>	// allocate something here that lives beyond the function
>	...
>	delete a;
>}
>
>
>
>
>Question for everybody in general: is there heap analysis tool that =
will
>check fragmentation of the heap?
>
>Dan Levi
>dlevi@hworks.com
>
>----------
>> From: Amir Shoval 
>> To: 'MFC list' 
>> Subject: Memory fragmentation & garbage collection
>> Date: Monday, March 31, 1997 12:33 AM
>>=20
>> Environment: Win 95, VC4.2b
>>=20
>> Hello,
>>=20
>> I've written a kind of network monitoring application. This =
application
>> should
>> be active for a long time, so I wanted to check that I'm not =
consuming a
>> lot
>> of memory over time.
>>=20
>> I'm quite sure I have the right delete for every new, and that the
>> delete occurs
>> not too long after the new. My question can be separated into two:
>>=20
>> 1) Can memory fragmentation (because of many 'new's and 'delete's of
>> relatively small objects) cause consuming a lot of memory?
>>=20
>> 2) If the answer to the above is YES, I know how to prevent
>> fragmentation=20
>> caused by objects created from my classes, but what about objects
>> created
>> from MFC classes? For example CString: It's variable part (actually =
the
>> string)
>> is allocated on the default heap, so if I have many CString objects,
>> they
>> probably increase fragmentation. How can I handle this situation?
>>=20
>> Any other general advise about memory fragmentation & garbage =
collecting
>> would be appreciated.
>>=20
>> 	10x,
>> 		Amir
>-----From: "Poul A. Costinsky" 
>
>> From: Amir Shoval 
>> Environment: Win 95, VC4.2b
>> Hello,
>> 1) Can memory fragmentation (because of many 'new's and 'delete's of
>> relatively small objects) cause consuming a lot of memory?
>
>Not only it can, but very probably will.
>
>> 2) If the answer to the above is YES, I know how to prevent =
fragmentation
>
>> caused by objects created from my classes, but what about objects
>> created from MFC classes?=20
>> For example CString: It's variable part (actually the string)
>> is allocated on the default heap, so if I have many CString objects,
>> they probably increase fragmentation. How can I handle this =
situation?
>
>If you know how to fight a fragmentation -:), the answer is simple:
>don't use CStrings in your long-term objects. You should also call
>defragmentation
>routines sometimes.
>
>> Any other general advise about memory fragmentation & garbage =
collecting
>> would be appreciated.
>
>In Win 95 you can use local memory heaps: one for each size of the =
object
>or category of the classes. Look at my home page for more details.
>
>> 10x,
>B'vakasha.
>----------
>
>Hope this helps.
>Regards,
>Poul.
>  ("`-''-/").___..--''"`-._     ~~~~~~~~~~Poul A. Costinsky~~~~~~~~~~
>    (`6_ 6  )   `-.  (     ).`-.__.`)     =
Poul@wizsoft.com.NOSPAM.PLEASE
>     (_Y_.)'  ._   )  `._ `. ``-..-'
>   _..`--'_..-_/  /--'_.' ,'
>  (il).-''  (li).'  ((!.-    http://www.wizsoft.com/~Poul
>=3D=3D=3D=3D=3D=3D=3D=3D=3D=3DDisclaimer:All my words are my =
own.=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
>
>
>
>
-----From: Alex Fok 

Amir Shoval wrote:
> 
> Environment: Win 95, VC4.2b
> 
> Hello,
> 
> I've written a kind of network monitoring application. This application
> should
> be active for a long time, so I wanted to check that I'm not consuming a
> lot
> of memory over time.
> 
> I'm quite sure I have the right delete for every new, and that the
> delete occurs
> not too long after the new. My question can be separated into two:
> 
> 1) Can memory fragmentation (because of many 'new's and 'delete's of
> relatively small objects) cause consuming a lot of memory?
> 
> 2) If the answer to the above is YES, I know how to prevent
> fragmentation
> caused by objects created from my classes, but what about objects
> created
> from MFC classes? For example CString: It's variable part (actually the
> string)
> is allocated on the default heap, so if I have many CString objects,
> they
> probably increase fragmentation. How can I handle this situation?
> 
> Any other general advise about memory fragmentation & garbage collecting
> would be appreciated.
> 
>         10x,
>                 Amir

-- 
I think that memory fragmentation & garbage collection belong to memory
management area.
Is memory management a job of Application? I think that good designed
operating system should do garbage collection itself.
I think Unix, for example, does. Is Win95/Win NT good designed operating
systems from this point of view? Has anyone tested it?

 ____________________________________________________________
|                     |                                      |
| Alexander Fok       | E-mail:  alexp@sharnoa.co.il         |
| Software Engineer   | Office:  +972-7-6285058              |
|                     |    Fax:  +972-7-6277859              |
| Xtrol (Sharnoa)     | Home:    +972-7-6271886              |
| Corporation Israel  | WWW : http://www.cs.bgu.ac.il/~alexf |
|_____________________|______________________________________|



Mike Blaszczak -- mikeblas@nwlink.com
Wednesday, April 02, 1997

[Mini-digest: 2 responses]

>-----From: Amir Shoval 

>To continue the discussion, I am using fixed heaps for 3 of my classes
>which are allocated (and freed) dynamically in large quantities.
>The second answer talks about 'defragmentation routines'. What are
>these?

They are routines that coalesce free space in the heap.  They can be
expensive to call, so you can actually _hurt_ performance by calling
too often.

If you're using Win32 SDK heaps that you've gotten from the ::HeapAlloc()
API, you can call the ::HeapCompact() API to compact the heap. If you're
using the C Runtime's heap, you can call _heapmin().

>Can I defragment the default heap somehow?

If you mean the default Win32 heap for your process, you can get a
handle to it by calling the ::GetProcessHeap() API.  Then, call
the ::HeapCompact() API on the API.

>From both answers it seems MFC is NOT suitable for writing a
>continuously running application. Is it true (Mike B.)?

No, it isn't.  MFC does lots of work for you, and makes many things simpler,
but it doesn't excuse you from thinking about your application.  If
you know your application is going to run forever, you need to
worry about some issues.  This is one of the most important. 

That you need to worry about certain issues when writing software is
true no matter what tool or library you do (or don't!) use.


.B ekiM
http://www.nwlink.com/~mikeblas/
These words are my own. I do not speak on behalf of Microsoft.
       One is too many and a million is not enough.
-----From: Luc-Eric Rousseau 

At 08:20 PM 4/1/97 -0800, you wrote:
>>Question for everybody in general: is there heap analysis tool that will
>>check fragmentation of the heap?
>
>You can write your own using the _heapwalk() function provided by the CRTL.
>
>I think heap fragmentation is really not worth worrying about, though, aside
>from a very few specific (and pretty esoteric) cases. If you're worried about
>some objects being allocated and freed very quickly, your best bet is to
>override operator new() and operator delete() for the class that implements 
>those objects.

Our tax income program's heap (made with VC 1.5x) just grows and grows and
grows through the day.  (No, we pass the thing through Bound Checker and
there are not memory leaks).

I can't understand how you can say that heap fragmentation could not be a
problem with a program that runs all day.  We probably have 500 CString
allocated at any one time.  And as users open and close files, the strings
get freed and possibly realocated.  Large memory blocks get fragmentated
into smaller ones and after a while the heap manager doesn't seem to be
able to find more.  Maybe a heap manager replacement (like SmartHeap) could
help.

>Without hearing any details of Amir's application, it's hard to tell if he's
>having problems with fragmentation or not: this might be a wild goose chase.
>
>As Poul points out, you can call _heapmin().  But there's no real reason to
>avoid CString (or favor basic_string, or avoid basic_string); it's not going
>to fragment memory any more heavily than dynamically allocating your own
>array of TCHARs if the string content isn't changing a lot.  If it the
>content _is_ changing heavily, the effects of CString's reallocations can
>be minimized by preallocation while the effects of basic_string's can be
>minimized by replacing the allocator implementation.

Does heapmin() actually do something?  It's my expererience that calling it
doesn't do much expect in very extreme cases.






Marion Nalepa -- mnalepa@ontime.com
Thursday, April 03, 1997

[Mini-digest: 2 responses]

>If you know your application is going to run forever, you need to
>worry about some issues.  This is one of the most important. 

Are the relevant issues regarding forever-running MFC programs 
documented anywhere? 





-----From: "Adam Miller" 


I wouldn't tend to worry about fragmentation in a typical GUI application.
However, if there is need it makes sense to attempt to organize memory.
OS paging is something that always concerns me.  If I can help the OS
out by organizing memory such that frequently hit addresses exist
within similiar pages, that only lessens the burden on the paging the OS
would do.

For instance, if you need to maintain a large collection of objects
of your own, it would probaly improve things to overide new/delete
and use the Heap API's.  Especially if you need to access these
objects often.  It would help the OS out by allowing it to organize
those memory pages in a contiguous fashion.


The other approach typically taken is to use the memory pool method.
A mem pool allocator will typically round up the requested size to some
power of 2.  It will maintain each of these pools seperately.  This method
could improve performance when using many short-lived, small allocations or
using a lot of asynch I/O and maintaing buffers for reads and writes.

I've had success with using the OSE class library in an MFC app.
OSE has template collection classes, a mem-pool allocator, string classes,
object reference counting and lots of other neat stuff.  Almost all objects
are allocated out of memory pools.

I find it more stable and usable than STL currently, and it is
portable across WIN32 and Unix based OS's.
The compilation/installation procedure is a little tough going but it
does work nicely.  Source is provided and the license is free for
commercial
use.

OSE is at http://www.dscpl.com.au/ose.html

Adam Miller
royalblue technologies






Mike Blaszczak -- mikeblas@nwlink.com
Thursday, April 03, 1997

[Mini-digest: 2 responses]

>-----From: Luc-Eric Rousseau 
>Our tax income program's heap (made with VC 1.5x) just grows and grows and
>grows through the day.  (No, we pass the thing through Bound Checker and
>there are not memory leaks).

Just because something gets through BoundsChecker cleanly doesn't mean
that it doesn't have leaks.

>I can't understand how you can say that heap fragmentation could not be a
>problem with a program that runs all day. 

I can't understand how you can put words into my mouth. I was answering
someone who was using a version of Visual C++ and MFC and the C Runtimes for
Win32, not for Win16. You're using Win16, while the fellow I was answering
was using Win32.

>Does heapmin() actually do something? It's my expererience that calling it
>doesn't do much expect in very extreme cases.

Look at the sourcecode and figure it out yourself. If I were to answer you,
you'll just put words into my mouth and make the answer sound the way you
want it to, anyway. Again. So I'd rather save myself the time and
frustration.


.B ekiM
http://www.nwlink.com/~mikeblas/
These words are my own. I do not speak on behalf of Microsoft.
       One is too many and a million is not enough.
-----From: Olivier PLANCHON 

Hello ,

as a general contribution to the question, I generated a 'heap simulator'
and tryed some simulations :

method :
=======
1st allocate N>1000 contiguous blocks of data.
the size of one block is random from 1 to 1000
2nd randomly delete one of them and allocate a new one (of != size)

result :
=======
the situation quickly stabilize to an equilibrium :
1) number of fragments = N/2
2) total amount of memory used < 1.2 * total size of data

discussion :
===========
1) a new data block is always allocated closed to a previous one,
never in the middle of a free memory segment, 
so the worst we can get is 1 heap block for 2 data blocks.
This worst situation is quickly reached.

2) at the equilibrium, the median size of a fragment of free memory 
in the heap is less than the median size of a new element. If it was'nt,
a new element has a probability of 50% to fit in half of the holes, 
so the mean size of a free fragment has>50% to decrease.

conclusion :
===========
The real problem whith memory fragmentation is not the amount of memory
because it will never spoil a large amount of space.

The problem is the number of fragments : they tend to = half of
the number of data blocks.

If the number of objects (not their size !) your app have to handle at
the same time is about twice or more the number of heap fragments the 
heap manager can support(*), you will have to look for garbadge collecting.
Elsewhere, just don't care.

(*) I just don't know this. at least 10000 per heap ? (Is it, Mike B. ?)

>>> From: Amir Shoval 
>>> To: 'MFC list' 
>>> Subject: Memory fragmentation & garbage collection
>>> Date: Monday, March 31, 1997 12:33 AM
>>>=20
>>> Environment: Win 95, VC4.2b
>>>=20
>>> Hello,
>>>=20
>>> I've written a kind of network monitoring application. This =
>application
>>> should
>>> be active for a long time, so I wanted to check that I'm not =
>consuming a
>>> lot
>>> of memory over time.
>>>=20
>>> I'm quite sure I have the right delete for every new, and that the
>>> delete occurs
>>> not too long after the new. My question can be separated into two:
>>>=20
>>> 1) Can memory fragmentation (because of many 'new's and 'delete's of
>>> relatively small objects) cause consuming a lot of memory?
>>>=20
>>> 2) If the answer to the above is YES, I know how to prevent
>>> fragmentation=20
>>> caused by objects created from my classes, but what about objects
>>> created
>>> from MFC classes? For example CString: It's variable part (actually =
>the
>>> string)
>>> is allocated on the default heap, so if I have many CString objects,
>>> they
>>> probably increase fragmentation. How can I handle this situation?
>>>=20
>>> Any other general advise about memory fragmentation & garbage =
>collecting
>>> would be appreciated.
>>>=20
>>> 	10x,
>>> 		Amir
---------------------------------------
Olivier PLANCHON, ORSTOM, BP 1386 Dakar
tel(221) 32 34 80    fax (221) 32 43 07
e-mail Olivier.Planchon@orstom.sn





Become an MFC-L member | Вернуться в корень Архива |