c - 字符串终止还是悬空指针?

标签 c shell pointers posix clion

来自输出foo �您同意我在字符串终止方面遇到问题吗?我已经编写了一个自定义 shell,但是当我运行命令 echo foo 时然后我得到一些垃圾char看起来像一个悬空指针或一个未终止的字符串:

/home/dac/.CLion2016.1/system/cmake/generated/openshell-69ebaaf9/69ebaaf9/Debug/openshell
'PATH' is set to /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin.
dac:/home/dac/.CLion2016.1/system/cmake/generated/openshell-69ebaaf9/69ebaaf9/Debug $ ls
 {ls}
19660: executing ls
CMakeCache.txt  cmake_install.cmake  openshell
CMakeFiles  Makefile         openshell.cbp
dac:/home/dac/.CLion2016.1/system/cmake/generated/openshell-69ebaaf9/69ebaaf9/Debug $ echo foo
 {echo} {foo}
19669: executing echo
foo �
dac:/home/dac/.CLion2016.1/system/cmake/generated/openshell-69ebaaf9/69ebaaf9/Debug $ 

它在调试器或 Clion 分析中没有说明任何内容,但从输出来看,很明显我没有终止该字符串。你同意?如何在 Clion 中调试它?如果我在 gdb 中运行它然后就没有什么有趣的事情出现了。我想学习使用调试器,以便我可以在运行时实际检查值。

更新

当我小心的时候,它确实在调试器中说了一些话。事实证明 a 并没有终止争论: {"echo", "foo", 0x....}应该是{"echo", "foo", 0}当我修复它时,程序运行良好,没有垃圾 char (即 0x2525252525... )。

enter image description here

所以我稍微改变了代码:

static int runCmd(const char *cmd) {
    const char *cp;
    pid_t pid;
    int status;
    struct command shellcommand[4];
    char **argv;
    int argc = 1;
    bool pipe = false;
    char *command[40];
    char *cmd2[20] = {"cmd2", 0};
    int numberofpipelines = 0;
    unsigned long i3 = 0;
    unsigned long i2 = 0;
    unsigned long i1 = 0;
    unsigned long n = 0;
    char *string;
    char *string1;
    int maxgrep = 1;
    cmd2[0] = NULL;
    cmd2[1] = NULL;
    cmd2[2] = NULL;
    command[0] = NULL;
    command[1] = NULL;
    command[3] = NULL;
    char *string2 = NULL;
    for (cp = cmd; *cp; cp++) {
        if ((*cp >= 'a') && (*cp <= 'z')) {
            continue;
        }
        if ((*cp >= 'A') && (*cp <= 'Z')) {
            continue;
        }
        if (isDecimal(*cp)) {
            continue;
        }
        if (isBlank(*cp)){
            continue;
        }
        if ((*cp == '.') || (*cp == '/') || (*cp == '-') ||
            (*cp == '+') || (*cp == '=') || (*cp == '_') ||
            (*cp == ':') || (*cp == ',') || (*cp == '\'') ||
            (*cp == '"')) {
            continue;
        }
    }
    makeArgs(cmd, &argc, (const char ***) &argv, pipe);
    char a[20] = {0};
    if (sscanf(cmd, "%*[^']'%[^']'", a) == 1) {
        printf("<undefined>");
    }

    for (int i = 0; i < argc; i++) {
        if (argv[i] != NULL && strstr(argv[i], "|")) {
            numberofpipelines++;
            char subbuff[40];
            i1 = 0;
            i2 = 0;
            i3 = 0;
            subbuff[0]='\0';
            string = strstr(argv[i], "|");
            if (string != NULL) {
                i3 = string - argv[i];
            }
            string1 = strstr(&argv[i][i3 + 2], "|");
            if (string1 != NULL) {
                i2 = string1 - argv[i3 + 1];
                printf("i2: %lu", i2);
            } else {
                char *found3 = strstr(&argv[i][i3 + 1], " ");
                if (found3 != NULL) {}
                string2 = strstr(argv[1], "|");
                if (string2 != NULL) {
                    i1 = string2 - argv[1];
                }
                n = strlen(argv[1]) - i1;
                if (argc > 2) {
                    memcpy(subbuff, &argv[i][i3 + 1], n - 1);
                    subbuff[n - 1] = '\0';
                    cmd2[0] = subbuff;
                    cmd2[1] = argv[argc - 1];
                } else {
                    memcpy(subbuff, &argv[i][i3 + 1], n);
                    subbuff[n] = '\0';
                    cmd2[0] = subbuff;
                    cmd2[1] = argv[argc - 1];
                }
                argc++;
                argv[i + 1] = subbuff;
                command[i] = "<undefined>";
                argv[i + 2] = NULL;
                maxgrep = i;
            }
        }
        if (argv[i] != NULL) {
            if (i < maxgrep) {
                command[i] =  argv[i];
                command[i+1] =  0;
                maxgrep++;
            } else {
                command[maxgrep] =  argv[maxgrep];
            }
        }
        if (argv[i] != NULL) {
            char *p = strchr(argv[i], '|');
            if (!p) {
                /* deal with error: / not present" */;
            } else {
                *p = 0;
            }
        }

    }
    dump_argv((const char *) "d", argc, argv);
/*  makeArgs(cmd, &argc, &argv, pipe);*/
 /*   command[2]= 0;*/
    shellcommand[0].argv = command;
    shellcommand[1].argv = cmd2;
    pid = fork();
    if (pid < 0) {
        perror("fork failed");
        return -1;
    }
    /* If we are the child process, then go execute the program.*/
    if (pid == 0) {
        /* spawn(cmd);*/
        fork_pipes(numberofpipelines, shellcommand);
    }
    /*
     * We are the parent process.
     * Wait for the child to complete.
     */
    status = 0;
    while (((pid = waitpid(pid, &status, 0)) < 0) && (errno == EINTR));
    if (pid < 0) {
        fprintf(stderr, "Error from waitpid: %s", strerror(errno));
        return -1;
    }
    if (WIFSIGNALED(status)) {
        fprintf(stderr, "pid %ld: killed by signal %d\n",
                (long) pid, WTERMSIG(status));

        return -1;
    }
    return WEXITSTATUS(status);
}

现在输出看起来更好了。

/home/dac/.CLion2016.1/system/cmake/generated/openshell-69ebaaf9/69ebaaf9/Debug/openshell
'PATH' is set to /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin.
dac:/home/dac/.CLion2016.1/system/cmake/generated/openshell-69ebaaf9/69ebaaf9/Debug $ echo foo
i rcommand {echo} {foo}
926: executing echo
foo
dac:/home/dac/.CLion2016.1/system/cmake/generated/openshell-69ebaaf9/69ebaaf9/Debug $ 

最佳答案

检查输出之前的字符串值。如果您使用 printf 且仅使用 POD 字符数组,请确保最后一个字符是 '\0',并且它位于应有的位置(字符串正确终止并且末尾没有垃圾)。如果您在 C++ 中使用 std::string,请确保使用正确的值构造它(与以前的规则相同),并让 C++ stdlib 处理输出和格式化。看起来你最后有一些无法打印的数据。

关于c - 字符串终止还是悬空指针?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36846806/

相关文章:

c++ - 确定字符中设置位的数量

c - 在c中生成字指针数组

c - 获取位域的地址

c++ - 为什么指针地址的输出不同?

c - 使用 void 返回数组的内存地址

c - 注入(inject)的 dll 使所有者进程崩溃。为什么?

sql - mysqldump - 选择包含特定字符串的表

ios - mac 应用程序命令行工具上的应用程序传输策略

linux - 使用 shell 脚本在配置文件中追加行

c++ - 在 C++ 中(不在 C 中)具有未指定边界的数组指针的可用情况