C代码在Windows中崩溃,但在Linux中崩溃

时间:2012-08-03 21:51:10

标签: c windows linux

我是C的新手,我一直在Fedora中测试我的程序,使用gcc和gdb进行调试。我有一个程序,可以从用户那里获取输入。如果输入的第一个字符串是“create”,那么我看看第二个命令,如果那是“对象”,那么我将继续使用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中的行为相同?

4 个答案:

答案 0 :(得分:3)

您的代码中包含:

if(input[2] && strcmp(input[2], ""))

显然是在尝试检测input[2]是否存在而非空。

但是,这不起作用。没有承诺缺少第三个参数会使input[2]为NULL或""

input[2]此时可能会有垃圾值,但垃圾仍然会通过您的测试!

你有几个方法可以解决它 或者,此函数的调用者需要保证未设置为有效数据的元素将被设置为零/零。
或者,我更喜欢的方法,您将函数签名更改为某些内容像这样:

static void parseCmd(char **input, int num_inputs);

并将输入数与输入数组一起传递。

答案 1 :(得分:2)

您在此行中遇到问题:

if(input[2] && strcmp(input[2], ""))
你测试中的

输入[2] 不存在"创建对象",它解释了它崩溃的原因。

希望得到这个帮助。

问候。

答案 2 :(得分:1)

您已进入潜在访问冲突或未定义行为的领域(以及未定义的值):

input[2] && strcmp(input[2], "")

如果input的长度仅为2,那么这是读取超过可接受的读数点。最糟糕的情况是这将导致段错(如Windows所做),最好的情况是操作系统会让它发生,你会得到一个随机值。 (Linux似乎将它或* input [2]视为0。)

无论如何,不​​是阅读你不允许访问的内容,而是传入输入的长度并检查它。

static void parseCmd( char **input, size_t num) { //or just int if size_t isn't already defined
    //compare num
}

- 编辑 -

正如Daniel Fischer所指出的,显然argv[argc]确实是一个有效的读取,并且它保证是一个空指针。

假设您确实将argv传递给函数,这意味着您可以依赖此行为。你的另外两个if语句不会检查这个,并且为了概括函数,它仍然更好地传递长度(或者,正如paulsm4所说,你应该查看getopt函数 - 它使得parses参数更多比滚动自己的解析方法更容易。)

答案 3 :(得分:1)

你先生正在打击你无法击中的记忆。

我推荐你

How to check if a pointer is valid?

任何想知道他如何传递信息的人:

int main(void) 
{ 
    char* values[] = {"1", "2", "3"};
    parseCmd(values);
} 

当你试图访问输入[2]时会发生这种情况,但是如果你不知道你正在接受什么,它就会发生。当你得到输入时我会建议进行健全性检查。如果他们没有把任何东西放在值[2]中,让你的功能意识到这一点或改变它处理它的方式。使用指针和指针指针,在分配值时,不能忽视完整性检查。