-
Notifications
You must be signed in to change notification settings - Fork 31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Who manages STRING_ARRAY/STRING_POINTER? #472
Comments
from memory import alloc
string = "string1"
string2 = "string2"
s_p1 = alloc(len(string) + 1, False)
s_p2 = alloc(len(string2) + 1, False)
s_p1.set_string_array(string)
s_p2.set_string_array(string2)
# struct { char *s1;, char *s2; }
p = alloc(8, False)
p.set_pointer(s_p1)
p.set_pointer(s_p2, 4)
print("p.s1", p.get_string_pointer(), p.get_pointer().get_string_array())
print("p.s2", p.get_string_pointer(4), p.get_pointer(4).get_string_array())
p.get_pointer().dealloc()
p.get_pointer(4).dealloc()
# These are now freed...
print(s_p1.get_string_array())
print(s_p2.get_string_array()) |
I understand how get/set_string_array works, it is set_string_pointer I am asking about.
|
I will change the question, who determines the lifetime of this string object? When does it end? from memory import alloc
s_p1 = alloc(4, False)
s_p1.set_string_pointer("string") |
|
The actual behavior is not like that, set_string_pointer clearly sets the pointer of the string object. Code: from memory import alloc
p1 = memory.alloc(4, False)
print(p1.get_uint())
print(p1.get_pointer().address)
p1.set_string_pointer("string")
print(p1.get_uint())
print(p1.get_pointer().address)
print(p1.get_string_pointer())
p2 = memory.alloc(4, False)
print(p2.get_uint())
print(p2.get_pointer().address)
p2.get_pointer().set_string_array("string") Output:
|
This is not quite the equivalence. Let me bring some light into this topic by adding some comments to the very first example. set_string_pointer is actually a little bit dangerous, because you always have to keep a copy of the string alive in Python. As soon as your Python string is garbage collected, the pointer that has been set is also getting invalid. set_string_array is different, because it copies the bytes of the given string into an existing pointer. from memory import alloc
string = "string1"
string2 = "string2"
s_p1 = alloc(4, False)
s_p2 = alloc(4, False)
# These two calls are perfectly fine, because your string is stored in a Python
# variable. When you delete the variable "string" or assign a new value,
# the pointer is invalidated and it's not clear what exactly is returned by
# get_string_pointer. But let's continue in the example...
s_p1.set_string_pointer(string)
s_p2.set_string_pointer(string)
print("uint1", s_p1.get_uint())
print("uint2", s_p2.get_uint())
# This will cause undefined behaviour, because get_string_pointer returns a new(!) Python string
# which is then set using set_string_pointer. After that line the returned string is
# invalidated/forgotten by Python.
s_p1.set_string_pointer(s_p2.get_string_pointer())
# The following would work as we keep a copy of the string:
# new_string = s_p2.get_string_pointer()
# s_p1.set_string_pointer(new_string)
print("uint1", s_p1.get_uint())
print("uint2", s_p2.get_uint())
# Since s_p1 was set to a valid pointer, which was then invalidated, the result of
# s_p1.get_string_pointer() is now undefined.
print("string1", s_p1.get_string_pointer())
print("string2", s_p2.get_string_pointer())
# This will try to deallocated a pointer, which is not managed by you.
# This is the invalidated pointer that was managed by Python
s_p1.get_pointer().dealloc() |
I think this is an oversight of |
Yes, this is something you need to take care about. We are not able to determine maximum possible length. |
That seems to be the answer I was expecting, thank you. |
Yes, reading is fine, but writing requires some extra caution at the moment. |
@CookStar Do you have any further questions or can we close this issue? |
No more questions. Thanks for the answers. I have created a fix(#474) for some of the problems, so if you have any comments, please let me know. |
Who manages the char* set by Pointer.set_string_pointer? Is it impossible to set a string to a char* managed by a C++ object?
Test Code 1:
Output 1:
First, I don't know why string1 is set to
12
instead ofstring2
as in string2, but trying to free string1 would result in an illegal pointer deallocation. Who exactly is managing this char*?There is also a problem with TypeManager.pointer_attribute not being able to set STRING_ARRAY.
Test Code 2:
Output 2:
STRING_ARRAY also allows buffer overrun, and it seems that STRING-related issues are somewhat problematic.
The text was updated successfully, but these errors were encountered: