Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/image/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C语言中的断言和错误检查_C_Error Handling_Assert - Fatal编程技术网

C语言中的断言和错误检查

C语言中的断言和错误检查,c,error-handling,assert,C,Error Handling,Assert,我把我的代码贴在上面,得到的答案是我没有进行错误检查。AFAIK我可以通过几种方式进行错误检查: 前置条件和后置条件的断言 perror用法或类似用法,我有时会这样做,但我还没有学会 使用函数或类似函数的布尔返回值手动手动编码错误检查,指示调用成功或失败 有没有更多的方法或者推荐一些具体的方法?同时使用或和断言是好还是坏?代码处于中,main循环如下所示: int main(int argc, char *argv[]) { bool donotrun = false; st

我把我的代码贴在上面,得到的答案是我没有进行错误检查。AFAIK我可以通过几种方式进行错误检查:

  • 前置条件和后置条件的断言
  • perror
    用法或类似用法,我有时会这样做,但我还没有学会
  • 使用函数或类似函数的布尔返回值手动手动编码错误检查,指示调用成功或失败
有没有更多的方法或者推荐一些具体的方法?同时使用
和断言是好还是坏?代码处于中,
main
循环如下所示:

int main(int argc, char *argv[]) {
    bool donotrun = false;
    struct sigaction new_action, old_action;
    hashtable_t *hashtable = ht_create(65536);
    /* Set up the structure to specify the new action. */
    new_action.sa_handler = termination_handler;
    sigemptyset(&new_action.sa_mask);
    new_action.sa_flags = 0;

    sigaction(SIGINT, NULL, &old_action);
    if (old_action.sa_handler != SIG_IGN)
        sigaction(SIGINT, &new_action, NULL);
    sigaction(SIGHUP, NULL, &old_action);
    if (old_action.sa_handler != SIG_IGN)
        sigaction(SIGHUP, &new_action, NULL);
    sigaction(SIGTERM, NULL, &old_action);
    if (old_action.sa_handler != SIG_IGN)
        sigaction(SIGTERM, &new_action, NULL);


    void *pParser;
    char *c;


    int index = 0;
    int i;
    char *cvalue = NULL;
    const char *commandFile = "";
    bool quietFlag;

    while (1) {
        index = 0;
        i = getopt_long(argc, argv, "pc:vh",
                        options, &index);
        if (i == -1)
            break;
        switch (i) {
            case 'p': {
                exit(EXIT_SUCCESS);
            }
            case 'v': {
                printf("sh OpenShell version 0.1(a)\n");
                printf("Version: %s\n", VERSION);
                exit(EXIT_SUCCESS);

            }
            case 'h': {
                usage();
                exit(EXIT_SUCCESS);

            }
            case 'c': {
                cvalue = optarg;
                command(cvalue, hashtable);
                exit(EXIT_SUCCESS);
            }

            case 'f':
                /*
                 * Execute commands from file.
                 * This is used for osh script files.
                 * The quiet flag is also set.
                 */
                if ((argc != 1) || commandFile)
                    usage();

                quietFlag = true;
                argc--;

                break;


            case '?':
                if (optopt == 'c')
                    fprintf(stderr, "Option -%c requires an argument.\n", optopt);
                else if (isprint (optopt))
                    fprintf(stderr, "Unknown option `-%c'.\n", optopt);
                else
                    fprintf(stderr,
                            "Unknown option character `\\x%x'.\n",
                            optopt);
            default: {
                return 1;
            }
        }
    }
    getPath();
    pParser = (void *) ParseAlloc(malloc);
    char *copy = "";

    for (; ;) {
        bool scanning = true;
        bool calc = true;
        while (scanning) {
            char *line = NULL;
            line = readline("$ ");
            if (line == NULL) {
                /* No more lines, so exit the loop. */
                break;
            }
            if (line)
                copy = strdup(line);

            if (line && !strstr(line, "for") && !strstr(line, "==") && !strstr(line, "if") && strstr(line, "=")) {
                donotrun = true;
                char str[128];
                char *ptr;
                strcpy(str, line);
                strtok_r (str, "=", &ptr);
                ht_set(hashtable, str, ptr);
            }

            if (!scanning)
                break;

            if (!isatty(fileno(stdin))) {
                *argv++;
                readFile(*argv++, hashtable);
                free(line);
                exit(0);
            }
            else {

                if (!donotrun) {
                    line = str_replace(line, " | ", "|");
                    line = str_replace(line, " |", "|");

                    command(line, hashtable);
                }
                donotrun = false;
                add_history(copy);

            }
            free(copy);
        }
    }
    //  ParseFree(pParser, free);FIXME: where should this go?
    return 0;
}
然后我有一些断言,我必须在开发过程中注释掉,现在我不确定这些断言应该是什么

/* Returns a struct that has the number of "chunks" the list of chunks.
 * Splits the command by char | and then by whitespace and return a list of struct pointers
 */
struct str_list *list_split(const char *a_str, char *a_delim) {

    char **result = 0;
    size_t count = 0;
    char *tmp = (char *) a_str;
    char *ctmp;
    char *token = "";
    char *last_comma = 0;
    char *tmp2 = (char *) a_str; /* TODO: This variable can reuse tmp */
    //char *delim[2];
    //delim[0] = a_delim;
    struct str_list *chunks = NULL;
    /* Count how many elements will be extracted. */
    while (*tmp) {
        if (*a_delim == *tmp) {
            count++;
            last_comma = tmp;
        }
        tmp++;
    }
    /* Add space for trailing token. */
    count += last_comma < (a_str + strlen(a_str) - 1);
    count++;
    result = alloc_argv(count);
    char **tmpresult = alloc_argv(count);
    chunks = malloc(count * sizeof *chunks);
    if (result == NULL) {
        printf("Error allocating memory!\n");
        return chunks;;
    }
    if (result) {
        size_t idx = 0;
        token = strtok((char *) strdup(a_str), "|");
        int a = 0;
        while (token) {
//            assert(idx < count); Why must I turn off assertions?
            tmpresult[a] = strdup(token);
            a++;
            ctmp = strdup(token);
            *(result + idx++) = ctmp; /* memory leak! how to free() */;
            token = strtok(0, a_delim);
        }
//        assert(idx == count - 1);
        *(result + idx) = 0;
    }
    chunks->argv = alloc_argv(BUFFER_SIZE);//malloc(chunks->size * sizeof(char *) * 1);
    int i = 0;
    chunks = tokenize(&i, chunks, result, count, tmp2);
    chunks->pipes = i; /* important! to get this right */
    free(ctmp);
    return expand_shell(tmpresult, chunks);
}
/*返回一个结构,该结构包含块列表中的“块”数。
*按char |和空格拆分命令并返回结构指针列表
*/
struct str_list*list_split(const char*a_str,char*a_delim){
字符**结果=0;
大小\u t计数=0;
char*tmp=(char*)a_str;
char*ctmp;
char*token=“”;
char*last_逗号=0;
char*tmp2=(char*)a_str;/*TODO:此变量可以重用tmp*/
//char*delim[2];
//delim[0]=a_delim;
struct str_list*chunks=NULL;
/*计算将提取多少元素*/
而(*tmp){
如果(*a_delim==*tmp){
计数++;
最后一个逗号=tmp;
}
tmp++;
}
/*为尾部标记添加空间*/
计数+=最后一个逗号<(a_str+strlen(a_str)-1);
计数++;
结果=alloc_argv(计数);
字符**tmpresult=alloc_argv(计数);
chunks=malloc(count*sizeof*chunks);
如果(结果==NULL){
printf(“分配内存时出错!\n”);
返回块;;
}
如果(结果){
大小\u t idx=0;
token=strtok((char*)strdup(a_str),“|”);
int a=0;
while(令牌){
//断言(idxargv=alloc_argv(缓冲区大小);//malloc(chunks->SIZE*sizeof(char*)*1);
int i=0;
chunks=标记化(&i,chunks,result,count,tmp2);
chunks->pipes=i;/*重要!要正确执行此操作*/
免费(ctmp);
返回expand_shell(tmpresult,chunks);
}

据我所知,断言只能在开发和测试期间使用。assert实际上是一个宏。在调试配置中构建时,它将执行检查,如果为false,则退出。当您处于版本配置时,它什么也不做。因此,应使用assert检查编程错误

使用assert无法检查运行时错误,这意味着程序执行期间由于环境或用户输入而发生的错误,例如程序无法打开或写入文件,用户输入字符串(当需要数字时),无法建立网络连接,等等。您希望这些检查同时在调试和发布模式下进行

我认为您提到的另外两种错误检查方法,perror和检查返回值,总是同时进行的。通常检查函数的返回值,然后打印消息(使用perror或其他函数),然后执行错误恢复或退出。perror本身只打印一条消息,程序将继续运行,除非您执行其他操作


通常应检查外部函数调用的返回值,并检查程序的所有输入是否正确。大多数库函数可能会失败,包括malloc或printf,但取决于您的偏执程度,根据您的应用程序,只检查最有可能导致故障的函数(文件、网络、库或设备初始化等)就足够了。

等等,您是否询问检查您使用的东西是否有错误,还是你在问关于实现这样的错误发射和检查你自己开发的东西?@MarcusMüller我想知道为什么我必须注释我的断言,我想知道我应该在我编写的代码中使用断言。在某些地方,我已经使用了
perror
,但我不知道详细信息。
perror()
不检查错误。它只是将当前值
errno
的长文本错误消息记录到
stderr
中。当“发生了非常错误的事情,没有继续下去的意义”时,您可以使用断言@user3528438这正是我想知道的。“我应该在哪里使用断言?”我有断言,经过重构,然后我不得不注释掉断言,但代码起作用了。