我是一个新手,C,和我已经测试了我的程序在Fedora中,使用gcc和gdb调试。 我有一个程序,它从用户的输入。 如果输入的第一个字符串是“创造”,那么我就来看看第二个命令,如果是那样的“对象”,然后我继续CreateObject函数。
希望我的代码将使这更清楚一点:
static void parseCmd(char **input) {
if(!strcmp(input[0], "create")) {
if(!strcmp(input[1], "object")) {
if(input[2] && strcmp(input[2], ""))
createObject(input[2]);
else
printf("Object needs a name\n");
}
else
printf("Command needs more parameters\n");
}
else
printf("Command not recognized\n");
}
当我测试只输入“创建对象”(对象之后没有空间,只ENTER键)
在Linux中打印“对象需要一个名字”
但是在Windows的程序崩溃,它只是挂起。 我怎么能修改代码,使其行为相同的方式,因为它在Linux的呢?
你已经进入了潜在的访问冲突或不确定的行为(当然,未定义的值)的境界:
input[2] && strcmp(input[2], "")
如果长度input
仅为2,那么这是读过去可接受点阅读。 最坏的情况下,这将导致一个段错误(像Windows那样),而最好的情况下,操作系统将让它发生,你会在它获得一个随机值。 (Linux的似乎是治疗要么或*输入[2]为0虽然。)
不管怎么说,而不是读的内容你是不是允许访问,通过在输入的长度和检查来代替。
static void parseCmd( char **input, size_t num) { //or just int if size_t isn't already defined
//compare num
}
- 编辑 -
正如丹尼尔·菲舍尔指出,很显然argv[argc]
确实是一个有效的读取,并且可以保证它是一个空指针。
假设你确实传递argv
的功能,这意味着你可以依靠这种行为。 您的其他两个if语句不检查这虽然,和推广功能的缘故,它仍然是最好沿长度通(或如paulsm4说,你应该看看getopt的功能 - 它使解析参数太多比滚动自己的解析方法)更容易。
你有代码,上面写着:
if(input[2] && strcmp(input[2], ""))
显然试图检测是否input[2]
存在并且非空。
然而,这是不行的。 没有承诺,缺乏第三参数将使input[2]
为NULL或""
。
input[2]
将有可能在这一点上垃圾值,但垃圾还是会通过你的考验!
您有几种选择来解决它。
要么,这个函数的调用者需要保证没有设置元素有效的数据反而被设为零/零。
或者,我更喜欢的方法,你改变函数签名是这样的:
static void parseCmd(char **input, int num_inputs);
并与输入阵列一起传递的输入的数目。
你必须在此行的一个问题:
if(input[2] && strcmp(input[2], ""))
输入[2]在您的测试不存在“创建对象”,这是解释为什么它崩溃。
希望这有助于。
问候。
你先生正在打,你不能访问是击中内存。
我是指你
如何检查是否一个指针是有效的?
谁想要知道他是如何传递的东西:
int main(void)
{
char* values[] = {"1", "2", "3"};
parseCmd(values);
}
当您尝试访问输入[2],但它随时可能发生,如果你不知道你正在服用的是什么正在发生的事情。我会建议,当你所得到的输入健全检查。 如果他们不把价值观什么[2]让你的功能意识到或改变它处理它的方式。 随着指针和指向指针的指针,你不能吝啬的理智,当你分配值检查。