473,721 Members | 2,259 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

How properly manage memory of this PyObject* array?? (C extension)

Suppose a C extension locally built an array of PyObject* 's as
follows...

my_array = malloc(n * sizeof(PyObject *));
for (i = 0; i < n; i++) {
my_array[i] = PyList_New(0);
}

Q1: Must I do a Py_DECREF(my_ar ray[i]) on all elements
before exiting this C extension function? (What if
the elements got used in other objects?)

Q2: Must I do free(my_array); at end of function?? What if
my_array[i]'s are
used in other objects so that I can't necessarily just
nuke it!!!

Chris

Jul 9 '06 #1
11 3949
se******@spawar .navy.mil wrote:
Suppose a C extension locally built an array of PyObject* 's as
follows...

my_array = malloc(n * sizeof(PyObject *));
for (i = 0; i < n; i++) {
my_array[i] = PyList_New(0);
}

Q1: Must I do a Py_DECREF(my_ar ray[i]) on all elements
before exiting this C extension function?
if you're releasing my_array before existing, yes.
(What if the elements got used in other objects?)
if other parts of your program storing pointers to the elements in your
array, those parts must make sure to increment the reference count when
copying the pointer.

that's the whole point of reference counting, of course: the count for
an object should, at all times, match the number of *active* references
your program has to that object.
Q2: Must I do free(my_array); at end of function??
unless some other part of your program holds on to it, of course you
have to release it. it's a bit surprising that you have to ask this,
really -- any C tutorial should explain how malloc/free works.
What if my_array[i]'s are used in other objects so that I can't
necessarily just nuke it!!!
if those other objects do proper reference counting, everything will
work find. if they don't, your program will crash sooner or later, no
matter what you do in the function that allocates my_array.

</F>

Jul 9 '06 #2
Q2: Must I do free(my_array); at end of function??
unless some other part of your program holds on to it
F.

Thanks! If I understand you correctly then I never have
to do free(my_array); because all the elements
of my_array are still being used and appended to other
structures elsewhere right?

As long as each element of my_array is managed
properly and freed properly there is NEVER any
reason to worry about fact that free(my_array)
will never get run right?
cs

Jul 10 '06 #3
On 11/07/2006 4:39 AM, se******@spawar .navy.mil wrote:
>>Q2: Must I do free(my_array); at end of function??
unless some other part of your program holds on to it

F.

Thanks! If I understand you correctly then I never have
to do free(my_array); because all the elements
of my_array are still being used and appended to other
structures elsewhere right?
*WRONG* -- reread /F's response:
"""
unless some other part of your program holds on to it, of course you
have to release it. it's a bit surprising that you have to ask this,
really -- any C tutorial should explain how malloc/free works.
"""
>
As long as each element of my_array is managed
properly and freed properly there is NEVER any
reason to worry about fact that free(my_array)
will never get run right?
*WRONG* -- the reason to worry is that the memory occupied by the
my_array itself is never handed back. If you don't free it, repeated
calls to your function will cause your app to run out of memory.

It's quite simple, really: You malloc it, you free it. I share the
effbot's surprise: If you (or the taxpayers!) paid money for a
course/book/tutorial that didn't include that advice, a claim for a
refund is definitely indicated.

HTH,
John
Jul 10 '06 #4
It's quite simple, really: You malloc it, you free it.
John - I hope you don't mind that I really want to make sure I
understand your
good wisdom in this area by asking for clarification.. ..

ASSUMPTIONS:

1. As long as we properly handle the reference counting of PyObjects
then
memory management is taken care of for us. (i.e. You don't ever
use the 'free' command explicitly on a PyObject* but let Python
garbage collector
do the final freeing.)

2. All malloc'd stuff in C must be freed with free command. (Python
garbage
collector is limited to PyObjects. It won't free non-Python stuff
for us
like int arrays, char* strings, etc.)

.....

Now it would appear that if you **malloc an array of PyObjects**
(call it FOO[]) then you have an ambiguity....

The PyObject elements will be freed *for us* eventually by garbage
collector.
Hence, we can't ever do 'free(FOO); ' because we don't know when
garbage collector will free FOO[0], FOO[1], FOO[2], etc.

Chris

Jul 14 '06 #5
se******@spawar .navy.mil wrote:
Now it would appear that if you **malloc an array of PyObjects**
(call it FOO[]) then you have an ambiguity....

The PyObject elements will be freed *for us* eventually by garbage
collector.

Hence, we can't ever do 'free(FOO); ' because we don't know when
garbage collector will free FOO[0], FOO[1], FOO[2], etc.
you're not quite getting how reference counting works. the fact that
you have a pointer to a Python object stuffed away somewhere is
completely irrelevant to the Python garbage collector; all it cares
about is the reference count of the object itself. if the reference
count is not zero, someone somewhere might have a pointer to the object,
so the object must be preserved. if the reference count drops to zero,
nobody is supposed to have a pointer anymore, so the object can be removed.

if you use malloc to allocate a memory block and store PyObject pointers
in it, you must

1) make sure that the reference count is *incremented* (Py_INCREF) when
you add the objects (unless the object is new; when you create an
object, the reference count is set to 1). this tells Python that you
have a pointer to an object that you plan to use some time in the future.

2) make sure that the reference count is *decremented* (Py_DECREF) if
you remove the objects (this tells Python that *you* won't access the
object any more; if nobody else uses it either, it can safely be removed).

required reading:

http://docs.python.org/api/objects.html

</F>

Jul 14 '06 #6
On 14/07/2006 4:16 PM, se******@spawar .navy.mil wrote:
>It's quite simple, really: You malloc it, you free it.

John - I hope you don't mind that I really want to make sure I
understand your
good wisdom in this area by asking for clarification.. ..

ASSUMPTIONS:

1. As long as we properly handle the reference counting of PyObjects
then
memory management is taken care of for us. (i.e. You don't ever
use the 'free' command explicitly on a PyObject* but let Python
garbage collector
do the final freeing.)
That's correct: You didn't malloc it, you don't free it.

BTW, free is a function, not a "command".
>
2. All malloc'd stuff in C must be freed with free command. (Python
garbage
collector is limited to PyObjects. It won't free non-Python stuff
for us
like int arrays, char* strings, etc.)
Correct.

>
Now it would appear that if you **malloc an array of PyObjects**
(call it FOO[]) then you have an ambiguity....
No, not at all; there is no such action as "malloc an array of
PyObjects". Firstly, malloc does not produce an array of anything; it
allocates a chunk of memory and returns the address of the start of the
chunk. secondly, what you stuffing into that memory is not Python
objects but addresses of (a.k.a. pointers to) Python objects.
>
The PyObject elements will be freed *for us* eventually by garbage
collector.
Hence, we can't ever do 'free(FOO); ' because we don't know when
garbage collector will free FOO[0], FOO[1], FOO[2], etc.
Let's try reductio ad adsurdum on that one. Suppose that instead of
filling in a malloced chunk of memory, you had stored those gizmoids in
local variables foo0, foo1, foo2, etc. Using your reasoning: we can't
ever return from our function (which frees up the stack memory
containing foo0 etc) because we don't know when garbage collector will
free foo0 etc. Avoiding that problem would require a Python/C API
function with a name like Py_AwaitGarbage Collection() ... but there
isn't one.

HTH,
John

Jul 14 '06 #7
Let's try reductio ad adsurdum on that one. Suppose that instead of
filling in a malloced chunk of memory, you had stored those gizmoids in
local variables foo0, foo1, foo2, etc. Using your reasoning: we can't
ever return from our function (which frees up the stack memory
containing foo0 etc) because we don't know when garbage collector will
free foo0 etc. Avoiding that problem would require a Python/C API
function with a name like Py_AwaitGarbage Collection() ... but there
isn't one.
There are 2 memory components that make up a Python object.
First, there is the object in memory itself. Secondly, there
is the 4 bytes or so that hold the address to the object in memory.
(the 'pointer')

I think what I hear you saying is that garbage collection has
to automagically take care of my second component above as well.

So can I assume you are also saying our original malloc'd pointer
to Python objects will be take care of as well as the objects?
(Hence, no free(my_array) necessary?)
(Only Py_INCREFs and Py_DECREFs need apply?)

Chris

Jul 18 '06 #8
if you use malloc to allocate a memory block and store PyObject pointers
in it, you must

1) make sure that the reference count is *incremented* (Py_INCREF) when
you add the objects (unless the object is new; when you create an
object, the reference count is set to 1). this tells Python that you
have a pointer to an object that you plan to use some time in the future.

2) make sure that the reference count is *decremented* (Py_DECREF) if
you remove the objects (this tells Python that *you* won't access the
object any more; if nobody else uses it either, it can safely be removed).
OK, I'll read your 'required reading' I promise. Let me just make the
obvious
obvious for a minute. Your 'requirements' above only mention
Py_INCREFs and Py_DECREFs and never mention free(my_array).
Hence, I will assume the answer to my previous question is that I do
NOT
have to do free(my_array) because Py_INCREFs and Py_DECREFs will
allow garbage collection to take care of even the malloc'd part that
hold the pointers to the objects.

By the way, we are allowing garbage collector to free different
elements (pointers)
of my_array one at a time here. I just found out that curiously
enough, you CANNOT
do this in C with primitive types.

i.e. my_int_array = malloc(5 * sizeof(int));

You CANNOT do this...
free(&my_int_ar ray[1]);
free(&my_int_ar ray[2]);
free(&my_int_ar ray[3]);
...etc.
You can ONLY free the entire enchilada all at the same time...
free(my_int_arr ay);

Chris

Jul 18 '06 #9
On 18/07/2006 1:45 PM, se******@spawar .navy.mil wrote:
>Let's try reductio ad adsurdum on that one. Suppose that instead of
filling in a malloced chunk of memory, you had stored those gizmoids in
local variables foo0, foo1, foo2, etc. Using your reasoning: we can't
ever return from our function (which frees up the stack memory
containing foo0 etc) because we don't know when garbage collector will
free foo0 etc. Avoiding that problem would require a Python/C API
function with a name like Py_AwaitGarbage Collection() ... but there
isn't one.

There are 2 memory components that make up a Python object.
First, there is the object in memory itself. Secondly, there
is the 4 bytes or so that hold the address to the object in memory.
(the 'pointer')
*WRONG*. The object exists in and of itself. There may be one *or more*
references to it, via pointers, scattered about in memory; they are
*NOT* components of the object. A reference count is maintained inside
the object and manipulated by Py_INCREF etc. The Python garbage
collector knows *nothing* about the memory occupied by those pointers;
it is *your* responsibility to allocate and free them. If the pointers
are in a function's local variables, that memory is automatically
returned when you return from the function. If the pointers are in a
chunk of memory that you grabbed using malloc(), then you must free()
the chunk as soon as you are finished with it.

Like I said:

You malloced it? You free it.
You didn't malloc it? You don't free it.
>
I think what I hear you saying is that garbage collection has
to automagically take care of my second component above as well.
I'm terribly sorry, but there is no magic involved with memory
management at this level; only hard, tedious, error-prone work.

Python garbage collection has neither the responsibility nor the
necessary information for carrying out that task. *YOU* have that
information; it is *YOUR* responsibility.
>
So can I assume you are also saying our original malloc'd pointer
to Python objects will be take care of as well as the objects?
*NO* You must free() any memory that you malloc()ed.
(Hence, no free(my_array) necessary?)
*NO* You must free() any memory that you malloc()ed.
(Only Py_INCREFs and Py_DECREFs need apply?)
*NO* You must free() any memory that you malloc()ed.

"What I tell you three times is true" -- the Bellman in "The Hunting of
the Snark", by Lewis Carroll.

HTH,
John
Jul 18 '06 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
2079
by: Dhruba Bandopadhyay | last post by:
I have a problem. I have a C++ service and added a new API to it. I re-registered the service and re-added the reference in my ASP.NET Visual Web Developer. However when I call the new API I get: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
6
26418
by: Chris Ashley | last post by:
How can I manually release the memory held by a large array? I have tried setting the array to null but no joy. The garbage collector appears to be ignoring it completely.
2
1280
by: Si | last post by:
Thanks in Advance, I don't know if I need to copy the memory to an Array (thats what I would have done it in vb6), I just need to be able to read/access it. I have a Callback function that is handing me a block of memory - Function BufferCB(ByVal SampleTime As Double, ByVal pBuffer As IntPtr, ByVal BufferLen As Integer) As Integer Implements _ISampleGrabberCB.BufferCB SyncLock Me
6
49908
by: Sugandh Jain | last post by:
Hi, I am getting the error message Attempted to read or write protected memory. This is often an indication that other memory is corrupt. It was not coming until yet, for around 2 months. Now, may be the records have increased and so i am getting this. anyone has any idea why and when do we get this. Its a windows based application with c# 2.0 and .Net Framework 2.0.
0
1802
by: Mike | last post by:
How can i handle "attempted to read or write protected memory. this is often an indication that other memory is corrupt" I use VS 2005 framework 2.0 On the server explorer window I try to open tables from my db (MS Access db). DB is connnected properly and it works, but I'm unable to open DB and drag and drop tables on DataSet.xsd.... Finally, my goal is to make connection between CrystalReports and DataSet... It seems so far... :(
1
2818
by: Sudhan | last post by:
hi i am trying to write excel using VB.net but when i open oExcel.Workbooks.Open the application error: Attempted to read or write protected memory. This is often an indication that other memory is corrupt. can any one help me..
3
1935
by: Tony Adamoli | last post by:
Can someone tell me how to install ImageMagic on a Windows 2003 Small Business Server running PHP 5.2.5 and IIS 6.0? This has been driving me crazy for days. I have downloaded php_imagick.dll from the php4win.pecl.php.net site and copied it to my standard extentions directory. I have successfully installed the static 8-bit binary version of ImageMagick from their site. (ImageMagick works fine from the command line.) I have also added...
4
2469
by: somenath | last post by:
I have a question regarding the memory allocation of array. For example int array; Now according to my understanding 10 subsequent memory location will be allocated of size sizeof(int) *10 and this is done at compile time. Does it mean C compiler reserve some amount of memory for the array
1
1029
by: McLovin | last post by:
Hi, I have this error: Attempted to read or write protected memory. This is often an indication that other memory is corrupt. const char* char_9; string str_char_9;
0
8840
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9367
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9215
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9131
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9064
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8007
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
4484
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4753
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3189
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.