更新:找到一些解决方法。见下文。
我编写了一个C ++(几乎是C除了new
)函数,以便解析一个具有给定分隔符的字符串(以某种方式Cocoa的NSString -componentsSeparatedByString
等价物。)
我正在做一些断言以测试我的代码,我已经使用strlen
作为它的第一个元素。
实际上我是通过迭代使用这个功能的。不在其他方面,但在迭代的第一步中,我发现该字符串为"A"
,但strlen
计算的长度为4
。
所以我进入调试器并打印出值,字符串是正确的,但值是'\xef'
,'\xbb'
之类的字符。似乎存在内存损坏。
LLVM调试器也无法正确解释堆栈变量(我想),0x0
是什么意思?我知道它指的是0x0000000000000000
,但它是怎么来的?它也无法分辨数组的元素。
#ifndef BUFSIZ
#define BUFSIZ 1024
#endif
char **componentsSeparatedByString(const char *string, const char *delimiter) {
if (strcmp(string, "")) {
char **components = new char*[BUFSIZ + 1]();
// Copying string because strtok is destructive
char *input = new char[strlen(string) + 1]();
strcpy(input, string);
unsigned long count = 0;
char *token = strtok(input, delimiter);
while (token != NULL) {
components[count] = new char[strlen(token) + 1]();
strcpy(components[count++], token);
token = strtok(NULL, delimiter);
}
// Releasing that temporary string
delete input;
return components;
} else {
return nullptr;
}
}
以下是调试器的一些结果:
首先,linesArray
是char ***
,表示字符串数组的数组。它包含通过迭代由此函数解析的字符串。由于此函数返回一个字符串数组,linesArray
包含所有这些结果。
提到的断言是strlen(linesArray[i][0]) == 1
。这个断言只在迭代的第一步失败,其中i = 0
。之后没有错,所以我先尝试迭代的第二步:
(lldb) po linesArray[1][0]
"P"
(lldb) po linesArray[1][0][0]
'P'
(lldb) po linesArray[1][0][0] == 'P'
true
一切看起来都很棒。让我们为第一个做:
(lldb) po linesArray[0][0]
"A"
(lldb) po linesArray[0][0][0]
'\xef'
(lldb) po linesArray[0][0][0] == '\xef'
false
(lldb) po linesArray[0][0][0] == 'A'
false
如你所见lldb
与自身矛盾。我无法找出发生这种情况的原因。是否存在内存损坏?
以下是我从文件中获取原始字符串的代码:
char ***linesArray = new char**[BUFSIZ + 1]();
char **lines = new char*[BUFSIZ + 1]();
lines[0] = new char[BUFSIZ + 1]();
unsigned long count = 0;
std::ifstream file("whoo.mmp");
while (file.getline(lines[count], BUFSIZ)) {
lines[count][strlen(lines[count]) - 1] = '\0';
lines[++count] = new char[BUFSIZ + 1]();
}
for (CFUInteger i = 0; lines[i]; ++i) {
linesArray[i] = componentsSeparatedByString(lines[i], ";");
for (CFUInteger b = 0; linesArray[i][b]; ++b) {
std::cout << "line: " << i << ", command: " << b << " -> \"" << linesArray[i][b] << "\" : " << strlen(linesArray[i][b]) << '\n';
}
delete lines[i];
}
delete[] lines;
该断点处的内存十六进制转储,显示0x100300340
,linesArray[0][0][0]
指向的地址。
如有任何进一步的信息,可以根据要求添加,谢谢你的帮助。
将行结束字符从Unix更改为Windows,现在一切正常,除了最后一行。这也可以通过另一种解决方法来解决。
尽管如此,我还是无法说服自己那个解决方案,这是混淆的。我使用libstdc++
(GNU C ++标准库)作为标准库,gnu++11
作为C ++语言方言。
答案 0 :(得分:0)
你应该添加更好的边界检查一件事。我不认为strcmp(字符串,“”)将测试字符串是否为空,如果这是预期的。它只会测试一个空字符串。此外,使用分隔符而不进行检查。
我也希望你的代码可以删除在这个函数中用new分配的所有代码。您需要担心字符串数组以及正在创建的每个元素。
否则我不会立即看到任何错误,但如果你开始使用三指针,我会质疑我的设计。那就是说你知道你想要做的比我做得更好,所以我会告诉你。祝你好运。