由于某些原因我无法解释,字符数组中的每一项......等于添加到它的最后一项...例如progArgs [0]到progArgs [size]包含最后一项的值
我无法弄清楚我为自己的生活做错了什么。有什么建议吗?
int count = 0;
char *progArgs[commandList.size()]
for(list<string>::iterator t=commandList.begin(); t!=commandList.end(); t++)
{
char item[strlen((*t).c_str())]; //create character string
strcpy(item, (*t).c_str()); //convert from const char to char
progArgs[count] = item;
count++;
}
编辑:
感谢所有人的快速回复...我看到你在说什么
答案 0 :(得分:3)
progArgs
是一个指向char的指针数组。
您将每个指针设置为指向item
。 item
是循环中的局部变量,因此只要循环退出,item
就不再存在且指针不再有效[*]。但是,在您的C ++实现中,它们仍然指向曾经是堆栈上的数组item
的内存位。此内存包含上次使用的内容,即列表中最后一个字符串的字符序列。
如果要将字符串列表复制到数组中,最好尽可能使用字符串数组:
std::string progArgs[commandList.size()] // if your compiler has C99 VLAs as an extension
int count = 0;
for(std::list<std::string>::iterator t=commandList.begin(); t != commandList.end(); ++t) {
progArgs[count] = *t;
++count;
}
甚至更好,使用向量而不是数组:
std::vector<std::string> progArgs(commandList.begin(), commandList.end());
[*]更准确地说,item
的范围是循环的单个重复,它每次名义上“创建”和“销毁”。但是这没有做任何工作 - 在你的C ++实现上,每次重复使用相同的内存区域,并且不需要在堆栈上创建或销毁char数组。
答案 1 :(得分:3)
您正在为item
的每个元素分配相同的指针(堆栈数组progArgs
的第一个元素的地址),然后重复覆盖该内存。你可以这样做:
progArgs[count] = strdup(t->c_str());
并摆脱身体的前两行。
strdup
分配内存,因此您必须稍后使用free
释放每个元素。此外,您没有为NUL终结器分配字符。您需要strlen
+ 1。但是,这不是strdup
的问题,因为它会为您分配。
答案 2 :(得分:1)
item
具有循环的局部范围。因此propArgs
数组包含一堆基于堆栈的指针,可能都是相同的。您可以在调试器中检查它是如何工作的,只需循环两次循环,它应该清楚发生了什么。
当您退出循环时,公共指针寻址的缓冲区包含最近复制的c_str()
。
您可以通过执行
来解决此问题char* item = new char[strlen((*t).c_str()) + 1];
但是当你退出循环时,你必须删除[]所有propArgs
数组条目。
此代码显示了对内存管理的基本缺乏理解,因此在重构代码之前进一步阅读可能会有用。如果此处使用的代码仅比此示例稍微复杂一些,则它可能会崩溃,因为循环外propArgs
的任何访问都将依赖于无效(不再在范围内)item
。< / p>
答案 3 :(得分:0)
您每次都将progArgs[count]
设置为同一个项目!
int count = 0;
char *progArgs[commandList.size()]
for(list<string>::iterator t=commandList.begin(); t!=commandList.end(); t++)
{
char * item = new char[strlen((*t).c_str()) + 1]; //create new character string
strcpy(item, (*t).c_str()); //convert from const char to char
progArgs[count] = item;
count++;
}
然后记得为progArgs中的每个元素调用delete[]
。
就个人而言,我会创建一个string
数组,并根据需要动态转换为char *
。
答案 4 :(得分:0)
char
数组item
是局部变量,仅在for
循环中可用。
而是动态分配它。
答案 5 :(得分:0)
你是对的:
for(list<string>::iterator t=commandList.begin(); t!=commandList.end(); t++)
{
char item[strlen((*t).c_str())]; //create character string
...这确实会创建一个数组,但它会在堆栈上创建它,所以当你到达其范围的末尾时,它就会被破坏。
strcpy(item, (*t).c_str()); //convert from const char to char
progArgs[count] = item;
count++;
}
...而这个结束括号标志着其范围的结束。这意味着您正在创建一个字符串,将其放入您的数组中,然后在添加下一个字符串之前将其销毁。由于您在堆栈中创建了它们,因此您创建的每个新创建都与前一个创建完全相同,因此最后,您有一堆相同的字符串。
如果你告诉我们你在这里想要完成的事情,也许会更好,所以我们可以帮助你做到这一点。