Repository navigation
ctypes pointer not always keeping target alive #46376
Description
Activity
It's hard to tell for sure, given the lack of precise definition, but I
believe that the attached piece of code "should" work. What it does is
make p1 point to c_long(20). So ctypes should probably keep the
c_long(20) alive as long as p1 is alive (and not further modified).
This test shows that the c_long(20) gets freed instead, making the
p1.contents reference garbage.- addedextension-modulesC modules in the Modules dirC modules in the Modules dir
on Feb 15, 2008 May I ask: do you have a real use case for this, or is it a carefully
constructed example?Of course I take all the blame for not defining/documenting this
stuff. My current view is this:Python code C code
======================= ================ptr = POINTER(c_long)() int *ptr = NULL; x = c_long(42) int x = 42; ptr.contents = x ptr = &x; a = ptr[0] int a = *ptr; b = ptr[n] int b = ptr[n];
Assigning to .contents changes 'where the pointer points to'.
__setitem__ changes the pointed to memory location; __getitem__
retrieves the pointed to memory location.Having said that, it is no longer clear to me what reading the
.contents attribute should mean. Would making the .contents attribute
write-only help - is it impossible to construct this 'bug' without
assigning to .contents?We're finding such bugs because we are trying to reimplement ctypes in PyPy.
I guess your last question was "is it impossible to construct this 'bug'
without *reading* .contents?". The answer is that it doesn't change
much; you can replace all the reads from .contents with reads from [0],
and still see the issue. See attached y.py, where I've put the
equivalent C code in comments.Thomas, do you accept this as a bug or should the issue be closed as
invalid?- addedtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
on Mar 24, 2009 I accept this as a bug; however I don't have time now to work on it.
- addedstaleStale PR or inactive for long period of time.Stale PR or inactive for long period of time.
on Jul 10, 2013 This looks like it works as expected at least as of Python 3.7 where c_long(20) is indeed preserved and p1.contents removes 20 as expected.
Original examples would pass, but only because of gc delay.
Here's fun way to demonstrate that the problem still exists (and can be converted to a test):
import ctypes import weakref p1 = ctypes.pointer(ctypes.c_long(10)) w = weakref.WeakValueDictionary() ctypes.pointer(p1).contents.contents = w.setdefault( 1, ctypes.c_long(-1), ) assert p1.contents.value == -1 assert 1 in w
Reacted by Łukasz Langa and Gregory P. Smith24 remaining items
Please, take a look at
#108519- added a commit that references this issue
on Sep 4, 2023 - added a commit that references this issue
on Sep 4, 2023 - added a commit that references this issue
on Sep 4, 2023 - added a commit that references this issue
on Sep 4, 2023 - added 3 commits that reference this issue
on Sep 6, 2023
Metadata
Metadata
Assignees
Labels
Projects
- StatusShow more project fieldsNo status
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
Linked PRs