在 C# 中读取时,如何从 C++ 中获取 \0
Posted
技术标签:
【中文标题】在 C# 中读取时,如何从 C++ 中获取 \\0【英文标题】:How do I get \0 off my string from C++ when read in C#在 C# 中读取时,如何从 C++ 中获取 \0 【发布时间】:2009-12-06 17:01:30 【问题描述】:我有点卡在这里。我正在为 Commerce Server 2009 开发一个自定义 Pipleline 组件,但这与我的问题无关。
在管道的设置中,我给用户一个windows窗体来输入一些值进行配置。其中一个值是 SharePoint 网站的 URL。 Commerce Server 在所有这些管道内容背后使用 C++ 组件,因此输入的值被放入一个 IDictionary 并最终通过 Microsoft 的 C++ 组件持久化到 DB。
当我在管道执行期间读入字符串时,它会在 C++ 的 IDictionary 对象中交给我。我的 C# 代码看到该 URL 以 \0\0 为后缀。我不确定这些来自哪里,但我的代码崩溃了,因为它不是有效的 URI。我在保存之前修剪字符串,并在阅读时修剪它,但仍然无法摆脱这些。
任何想法是什么导致了这种情况以及如何摆脱它?我不希望有像子字符串这样的黑客攻击,而是要找到根本原因。
谢谢, 科里
【问题讨论】:
\0 来自 C/C++ 中的字符串以 \0(又名 null)终止的约定。它们被称为“以空字符结尾的字符串” 您的 c# 代码是否定义了编组?你得到一个 IDictionary 所以有问题的字符串是从一个对象中转换出来的?可以将对象编组或以其他方式转换为适当的字符串。你能发布一些有问题的代码吗? 【参考方案1】:这会有帮助吗:
string sFixedUrl = "hello\0\0".Trim('\0');
【讨论】:
我认为这会解决它,但它就像 Substring 一样是一个 hack。它没有解决问题的原因。 我认为根本原因一定是我无法控制的,正如 ltcmelo 所建议的那样。我将使用 Trim 解决方案,无论是否破解,因为它可以工作,并且我正在通过我编写的“NullSafeString”对象读取所有字符串,所以这已经足够好了,并且像冠军一样工作。【参考方案2】:正如其他人的帖子所解释的,C 中的字符串是空终止的。 (请注意,C++ 已经提供了一个不依赖于它的字符串类型。)
你的情况有点不同,因为你得到的是双空终止的字符串。我不是这里的专家,所以如果我错了,任何人都应该随时纠正我。但这看起来像是 Windows 中使用宽字符的 unicode/i18n 感知应用程序的典型字符串表示。请看this。
一种猜测是,将字符串保存到数据库中的应用程序没有使用“可移植”策略。例如,考虑到它的 原始字节 大小而不是它的实际 长度,它可能会持久化字符串缓冲区。前者最终会计算额外的两个零(因此也会保留它们),而后者会丢弃它们。
【讨论】:
【参考方案3】:来自this网站:
C 中的字符串只是一个字符数组,最后一个字符设置为 NUL 字符(ascii/unicode 点 0)。这个空终止符是必需的;如果字符串不存在,则字符串格式错误。 C/C++ 中的字符串文字标记(“字符串”)保证了这一点。
const char *str = "foo";
与
相同 const char *str = 'f', 'o', 'o', 0;
因此,一旦 C++ 组件获取您的 IDictionary,它就会在末尾添加以 null 结尾的字符串。如果要删除它,则必须在发回字典之前从末尾删除以空字符结尾的字符。请参阅this 帖子,了解如何删除以空字符结尾的字符。基本上你需要知道确切的尺寸并将其修剪掉。
【讨论】:
【参考方案4】:您可以使用的另一种技术是字符数组和数组的长度。字符数组不需要终止空字符。
当你传递这个数据结构时,你也必须传递长度。 C 风格字符串的约定是通过搜索“\0”(或在 Unicode 中为“\0\0”)来确定字符串的结尾。由于数组没有终止字符,因此始终需要长度。
一个更好的解决方案是使用std::string
。它不附加空字符。当您需要兼容性或 C 样式格式时,请使用 c_str()
方法。我必须在我的程序中使用这种技术,因为 GUI 框架有自己的字符串数据类型,它与std::string
不兼容。
【讨论】:
以上是关于在 C# 中读取时,如何从 C++ 中获取 \0的主要内容,如果未能解决你的问题,请参考以下文章