我90%肯定我在这里看到的奇怪结果是由我的代码触发的某种UB,但是,我找不到它:
cdef char** to_cstring_array(strings):
cdef char** result = <char**>malloc(len(strings) * sizeof(char*))
cdef bytes item
nelements = len(strings)
i = 0
while i < nelements:
s = str(strings[i]).encode("utf-8")
item = s
result[i] = item
i += 1
return result
cpdef object pykubectl_get(object items, object options=None):
cdef size_t nargs = len(items);
cdef bytes message
cdef char** args = to_cstring_array(items);
# message = args[0]
# print("1 items encoded: {}".format(message))
json_opts = json.dumps(options or {}).encode("utf-8")
cdef char* opts = json_opts
print("items: {}".format(items))
message = args[0]
print("2 items encoded: {}".format(message))
cdef ResourceGet_return result = kubectl_get(
opts,
len(json_opts),
<const char**>args,
nargs
)
free(args)
if result.r0.n == 0:
message = result.r1.p
raise Exception("kubectl failed: '{}'".format(message.decode("utf-8")))
message = result.r0.p
return json.loads(message.decode("utf-8"))
如果我取消注释将第一个参数分配给message
的行,则args
的内容会发生变化。我的猜测是编译器试图在这里优化一些东西,并且它可能与内存分配的完成方式有关,但我看不出它有任何问题。我也知道,原则上我不应该转向const char**
,但是我收到了不投的警告,所以我加了它。如果我忽略了警告并且没有施放,它就不会改变任何内容。
我没有发布生成的C代码,因为它很庞大......但如果这不可避免,我会把它发布到其他地方。
答案 0 :(得分:1)
result[i] = item
这将创建指向Python bytes
对象item
的第一个元素的指针。它不会导致item
保持活跃状态。一旦释放item
(可能在循环的下一次迭代中),指针就会立即失效。
你需要实际复制内存 - 例如:
cdef char* item_as_charp
# ....
# then in the loop
item_as_charp = <char*>malloc(sizeof(char)*len(item))
memcpy(item_as_charp,item, len(item))
(您可能需要使用len(item)+1
为null终止符提供空间)
当你完成这个记忆时,你需要释放这个记忆