【问题标题】:C - Function not terminating at end of input string leading to segmentation faultC - 函数未在输入字符串末尾终止导致分段错误
【发布时间】:2016-09-22 01:47:53
【问题描述】:

免责声明:这是家庭作业的一部分,但不是全部作业。

我的任务是创建一个“tokenizer”对象,该对象通过在每次调用 TKGetNextToken 时返回一次来检索由空格分隔的令牌,并对返回的令牌执行一系列操作。

但是,TKGetNextToken 函数的行为并不正常。应该发生的是:

  1. 遍历输入字符串,直到找到非空白字符。
  2. 继续遍历输入字符串,直到遇到空格或 NULL(指示字符串的结尾),然后将字符添加到新的 c 字符串中
  3. 如果遇到空格,则返回 c 字符串,并将字符串中的当前位置保存在 TokenizerT 结构中。
  4. 如果遇到 NULL,则返回 c 字符串,并将 NULL 存储在 TokenizerT 结构中,以便随后对 TKGetNextToken 的所有调用都返回 NULL。

但是,该函数不会在字符串的末尾停止,而是直接从字符串的末尾吹过并打印出内存中的所有内容,直到程序崩溃。我不知道为什么会这样。

这里是代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

struct TokenizerT_ {
    char *currentToken;
};

typedef struct TokenizerT_ TokenizerT;


char *TKGetNextToken(TokenizerT *tk) {
    char *cp = tk->currentToken;

    while (cp != NULL && isspace(*cp)) {
        cp++;
    }

    if (cp == NULL) {
        tk->currentToken = NULL;
        return NULL;
    }

    int size = 0;
    char *token = malloc(sizeof(char));

    while (cp != NULL && !isspace(*cp)) {
        size++;
        token = realloc(token, size * sizeof(char));
        token[size - 1] = *cp;
        cp++;
    }

    token = realloc(token, (size + 1) * sizeof(char));
    token[size] = NULL;

    tk->currentToken = cp;
    return token;
}

TokenizerT *TKCreate(char *ts) {
    TokenizerT *tokenizer = malloc(sizeof(TokenizerT));
    tokenizer->currentToken = ts;

    return tokenizer;
}

void TKDestroy(TokenizerT *tk) {
    free(tk);
}

int main(int argc, char **argv) {

    TokenizerT *tok = TKCreate(argv[1]);
    char *token = TKGetNextToken(tok);

    while (token) {
        printf("\'%s\'\n", token);
        token = TKGetNextToken(tok);
    }

    TKDestroy(tok);
    return 0;
}

这里是给定命令行参数“100 200 300 400”的示例输出。它显然是从输入字符串之外的内存中打印出来的。

'100'
'200'
'300'
'400'
''
'╘jÉ'
'╘hÉ'
''
''
''
''
''

以及来自 gdb 的输出

Program received signal SIGSEGV, Segmentation fault.
0x00401476 in TKGetNextToken (tk=0x701720) at test.c:28
28          while (cp != NULL && !isspace(*cp)) {
(gdb) backtrace
#0  0x00401476 in TKGetNextToken (tk=0x701720) at test.c:28
#1  0x0040151e in main (argc=2, argv=0x700cf0) at test.c:60

【问题讨论】:

  • "函数不会在字符串的末尾停止" --> 没有代码可以测试字符串的结尾。

标签: c string segmentation-fault


【解决方案1】:

在您的两个while 循环中,条件应该包括对空字符的测试。 “没有遇到字符串末尾的空字符”的适当测试是*cp,这样使用:

while ( cp != NULL && *cp && !isspace( *cp ) )

我感觉cp != NULL 测试是无令牌测试,在这种情况下,它们可能应该被排除在while 循环之外。如果这是错误的并且它们是字符串结尾测试,则应将它们替换为 *cp 测试。

【讨论】:

  • 你说得对,我需要检查空字符而不是检查地址是否指向空。我需要用*cp == '\0' 替换我的cp == NULL checks,因为*cp 检查对我不起作用。感谢您的帮助!
猜你喜欢
  • 2018-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多