c - 执行 "shimmering"的 Tcl 字符串函数破坏了我在 c 中定义的自定义 tcl 类型

标签 c tcl

我已经使用 c/c++ 中的 tcl 库定义了一个自定义的 tcl 类型。我基本上制作了Tcl_Obj.internalRep.otherValuePtr指向我自己的数据结构。调用 [string length myVar] 会出现问题或其他类似的字符串函数,称为闪烁行为,将我的 internalRep 替换为它自己的字符串结构。这样字符串系列tcl函数之后,myVar就无法转换回来了!因为它是一个复杂的数据结构,无法从 Tcl_Obj.bytes 转换回来表示加上类型不再是我自定义的类型。我怎样才能避免这种情况。

最佳答案

string length命令将其给出的值的内部表示转换为特殊的 string类型,它记录信息以允许快速执行许多字符串操作。除了大部分string命令的各种子命令,regexpregsub命令是执行此操作的主要命令(因为它们的字符串匹配-RE-against 参数)。如果您有自己宝贵的内部表示并且不想丢失它,那么您应该避免使用这些命令;有一些操作可以避免麻烦。 (Tcl 主要假设内部表示不是脆弱的,因此它们可以按需重新生成。使用脆弱时要小心!)

最安全的关键操作(如在需要时通过调用 bytes 生成 length/updateStringProc 代表,但不清除内部代表)是:

  • 替换成字符串;替换的值不会有内部代表,但它仍然会在原始对象中。
  • eq 的比较和 ne表达式运算符。这与检查值是否为空字符串特别相关。

  • 请注意,还有许多其他操作会以其他方式破坏内部表示,但大多数操作并没有把人们抓得那么紧。

    [编辑——评论太长了]:有许多相对知名的扩展以这种方式工作(例如,TCOM 和 Tcl/Java 都这样做)。你唯一能做的就是“小心”,因为值(value)观真的很脆弱。例如,将它们放在一个数组中,然后将索引传递到数组中,因为它们不需要是脆弱的。或者将事物作为元素保存在列表中(可能在全局变量中)并传递列表索引;这些只是普通的旧数字。

    传统的、健壮的方法是在您的 C 或 C++ 代码中放置一个映射(例如 Tcl_HashTablestd::map ),并将索引设置为没有太多含义的短字符串(我喜欢使用值的类型后跟一个序列号或指针的序列化,例如您可能通过 %p 中的 sprintf() 转换获得;打印的指针揭示了更多的实现细节,如果您这样做会更有帮助' 正在调试,通常在实践中实际上并没有太大的区别)。然后,您可以通过显式删除操作从 map 中删除内容,并且还可以轻松提供诸如列出所有已知当前值之类的操作。这是安全的,但容易“泄漏”(尽管如果您提供列表操作,这不是正式的内存泄漏)。它可以通过在 Tcl_Obj* 中缓存查找来加速。的内部表示(处理删除的一种廉价方法是使用在删除某些内容时递增的序列号,并且仅当您在 intrep 中缓存的序列号等于主序列号时才绕过映射查找)但是这通常没什么大不了的;如果您已经测量了查找中的瓶颈,则只进行那种事情。

    但我可能只是忍受我自己的代码的脆弱性,并且会注意确保我永远不会破坏这些假设。问题实际上是您对如何使用这些值很谨慎。 Tcl 代码应该只是传递它们而不是其他任何东西。另外,我已经尝试过将这些东西包装在 TclOO 对象中。对于你创造的值来说,它太重了(根据 TclOO 的设计),但是如果你只有其中的几个并且你想把它们当作带有方法的对象,这可以非常有效确实不错(并为自动清理提供了更多选项)。

    关于c - 执行 "shimmering"的 Tcl 字符串函数破坏了我在 c 中定义的自定义 tcl 类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41882867/

    相关文章:

    unix - 如何从 tcl 脚本运行 csh 脚本?

    c++ - 回调概念和正常调用

    TCL。如何检查程序是否存在?

    tcl - Tk帧: how to deactivate internal handler for expose events?

    tcl - 在TCL脚本中设置环境变量

    正则表达式分隔符 "::"Tcl

    c - CLion IDE 中的文件 I/O

    c - 在c中查找特定文件类型并保存

    c - 指向静态字符的 int 指针

    C - 以微秒精度在几秒钟内为我的程序计时