神奇的分割错误?

时间:2015-02-05 00:51:09

标签: c segmentation-fault

我已经看过网站上的其他类似问题,但我仍然没有看到我错过的内容。 C对我来说是一个新的,可怕的野兽,所以我确定它很简单,但是当代码到达fgets();行时,我会遇到分段错误(核心转储)在while循环中。

我尝试将字符串直接写入currentInput而仍然得到它,所以我想我以某种方式错误地访问字符串?

我的理解是,通过访问(程序?)无法访问的内存导致分段错误...

顺便说一下,有没有办法在strcmp()中使用字符串文字;所以我可以比较" END"?

void runCommands()
{
    char * currentInput = (char*)malloc(100); //100 char input buffer
    char * cmd = (char*) malloc(CMD_LENGTH);
    char * target = (char*) malloc(UID_LENGTH);
    char * key = (char*) malloc(KEY_LENGTH);
    char * endstr = "END";
    cmd = "UNDEF";
    target = "UNDEF";
    key = "UNDEF";
    ushort tokens;

    while (strcmp(cmd, endstr) != 0) //Run until command is "END"
    {
        printf("ENTER INSTRUCTION: ");
        fgets(currentInput, sizeof(currentInput), stdin); //FAULT OCCURS HERE
        tokens = sscanf(currentInput, "%[^,\n],%[^,\n],%s", cmd, target, key); //parse string for values
        if (tokens <= 3 && tokens >= 1) //ensure valid # of tokens passed
        {
            fprintf(stdout, "TOKENS:\nCMD: %s\ntarget: %s\nkey: %s\n", cmd, target, key);
            switch (tokens)
            //restore UNDEF for non-existent tokens
            {
            case 1:
                target = "UNDEF";
                /* no break */
            case 2: //intentional fallthrough
                key = "UNDEF";
                break;
            default:
                break;
            }
            /* handle commands */
            if (strcmp(cmd, endstr) == 0)
            {
                end(keyfile);
            } //write file and exit function
            else if (strcmp(cmd, "DELETE") == 0)
            {
                delete(target, key);
            } //delete specified key from UID
            else if (strcmp(cmd, "VALIDATE") == 0)
            {
                validate(target, key);
            } //valid/not valid based on key presence
            else if (strcmp(cmd, "ADD") == 0)
            {
                add(target, key);
            } //add key to target UID
            else if (strcmp(cmd, "PRINT") == 0)
            {
                print(target);
            } //print sorted keys for UID or all keys for ALL
            else
            {
                invalidCMD(cmd);
            } //error message for invalid command
        }
        else
        {
            invalidCMD(currentInput); //use whole input as bad command if invalid format
        }
    }
    free(currentInput);
    free(target);
    free(key);
    free(cmd);
}

3 个答案:

答案 0 :(得分:2)

通过覆盖malloc返回的指针值,导致内存泄漏和未定义的行为:

char * currentInput = (char*)malloc(100); //100 char input buffer
char * cmd = (char*) malloc(CMD_LENGTH);
char * target = (char*) malloc(UID_LENGTH);
char * key = (char*) malloc(KEY_LENGTH);
//...
// This is where you cause the issue
char * endstr = "END";
cmd = "UNDEF";
target = "UNDEF";
key = "UNDEF";

由于您关闭了代码,我无法对您的其余代码发表评论,以确定还会导致问题。

有一点是你肯定没有正确使用sizeof(),因为sizeof(currentInput)等于sizeof(char*),而不是字符串的长度。

答案 1 :(得分:1)

当您编写cmd = "UNDEF"时,您将指针(即cmd)设置为文字字符数组的位置。如果要分配字符串(而不是指向它们的字符串),则应使用strcpy

C编译器会自动为字符串常量分配空间,但是,它不允许重写它们,您可能会尝试在您省略的代码部分中进行重写。

答案 2 :(得分:0)

你需要读一下C类型和指针.. :)考虑下面的变化:

#define CMD_LENGTH 100
#define UID_LENGTH 100
#define KEY_LENGTH 100    
void runCommands()
    {
        char * currentInput = (char*)malloc(100); //100 char input buffer
        char * cmd = (char*) malloc(CMD_LENGTH);
        char * target = (char*) malloc(UID_LENGTH);
        char * key = (char*) malloc(KEY_LENGTH);
        char * endstr = (char *)malloc(sizeof(char) * 100);
        ushort tokens;

        strcpy(cmd, "UNDEF");
        strcpy(target, "UNDEF");
        strcpy(key, "UNDEF");

    while (strcmp(cmd, endstr) != 0) //Run until command is "END"
    {
        printf("ENTER INSTRUCTION: ");
        fgets(currentInput, sizeof(currentInput), stdin);

您不能使用简单的赋值以这种方式将值放入指针。这样做有效地覆盖指针与任何&#34; END&#34; (例如)转换为十六进制,这不是您的进程拥有的内存位置。实际上,如果您收到分段错误,通常意味着您尝试读取您不拥有的内存,而访问冲突通常是尝试写入您不拥有的内存。

我预计你的大部分麻烦都是由无意中覆盖指针造成的。

使用&#34;魔术数字&#34; ...(例如,神奇地分配100个字节,这也是非常糟糕的做法。你怎么知道它的100?它总是100?)您还应该验证malloc实际上是否返回了一个值,而不是假设它已经返回。调用Malloc的更典型方式也有说明,但我没有验证返回。最后,fgets是超级危险的,因为它是一个无限的读数。您更喜欢使用允许您指定要读取的最大大小的函数,以避免堆或堆栈上的溢出条件(取决于它是局部变量,全局变量还是指向堆的指针)。 / p>