C代码崩溃在Windows,但无法在Linux中(C code crashes in Windows

2019-09-20 18:26发布

我是一个新手,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的呢?

Answer 1:

你已经进入了潜在的访问冲突或不确定的行为(当然,未定义的值)的境界:

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的功能 - 它使解析参数太多比滚动自己的解析方法)更容易。



Answer 2:

你有代码,上面写着:

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

显然试图检测是否input[2]存在并且非空。

然而,这是不行的。 没有承诺,缺乏第三参数将使input[2]为NULL或""

input[2]将有可能在这一点上垃圾值,但垃圾还是会通过你的考验!

您有几种选择来解决它。
要么,这个函数的调用者需要保证没有设置元素有效的数据反而被设为零/零。

或者,我更喜欢的方法,你改变函数签名是这样的:

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

并与输入阵列一起传递的输入的数目。



Answer 3:

你必须在此行的一个问题:

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

输入[2]在您的测试不存在“创建对象”,这是解释为什么它崩溃。

希望这有助于。

问候。



Answer 4:

你先生正在打,你不能访问是击中内存。

我是指你

如何检查是否一个指针是有效的?

谁想要知道他是如何传递的东西:

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

当您尝试访问输入[2],但它随时可能发生,如果你不知道你正在服用的是什么正在发生的事情。我会建议,当你所得到的输入健全检查。 如果他们不把价值观什么[2]让你的功能意识到或改变它处理它的方式。 随着指针和指向指针的指针,你不能吝啬的理智,当你分配值检查。



文章来源: C code crashes in Windows, but not in Linux
标签: c windows linux