停止printf打印两次在C中运行检查框架?

时间:2015-03-08 04:06:42

标签: c printf buffer check-framework

  1. 可能深入解释c和c线程中的一般打印方式会解决问题
  2. 在任何时候都没有使用循环和scanf
  3. 因为我的代码使用了检查框架,所以我认为会有一些分析。
  4. 最有可能与缓冲区有关,所以我使用fflush(stdout),如果是因为框架内部的东西,我会感谢有人知道框架会解释会发生什么。
  5. 检查框架页面check.sourceforge.net
  6. Git链接,如果这可能有所帮助https://github.com/batousik/Practical-C2
  7. 链接到构建/测试日志,在第438行打印开始https://travis-ci.org/batousik/Practical-C2/builds/53513707
  8. 代码示例

    START_TEST(test_START_EMPTY_TREE_TREEBASE_PRINT_FREETREE_TEST) {
        printf("_________START_EMPTY_TREE/TREEBASE_PRINT/FREETREE_TEST__________\n");
        fflush(stdout);
    
        int *ptr;
        for (int i = 0; i < arr_size; i++) {
            ptr = malloc(sizeof(int));
            memcpy(ptr, (int_arr_ptr + i), sizeof(int));
            insert(ptr_tree_base_int_1, ptr);
        }
        // should print tree
        printf("!!!Next lines has to be tree printed out\n");
        fflush(stdout);
        ck_assert_int_eq(printTree(ptr_tree_base_int_1), true);
        printf("_____________________\n");
        fflush(stdout);
    
        // No output
        ck_assert_int_eq(freeTree(ptr_tree_base_int_1), true);
        // should print cannot free empty tree
        printf("!!!Next line has to be:\"cannot free empty tree\"\n");
        fflush(stdout);
        ck_assert_int_eq(freeTree(ptr_tree_base_int_1), true);
    
        // should print cannot print empty tree
        printf("!!!Next line has to be:\"cannot print empty tree\"\n");
        fflush(stdout);
        ck_assert_int_eq(printTree(ptr_tree_base_int_1), false);
        printf("_____________________\n");
        fflush(stdout);
    
        ptr_tree_base_int_1 = NULL;
        free(ptr_tree_base_int_1);
    
        // should print cannot free empty tree base
        printf("!!!Next line has to be:\"cannot free empty tree base\"\n");
        fflush(stdout);
        ck_assert_int_eq(freeTree(ptr_tree_base_int_1), true);
    
        // should print cannot print empty tree base
        printf("!!!Next line has to be:\"cannot print empty tree base\"\n");
        fflush(stdout);
        ck_assert_int_eq(printTree(ptr_tree_base_int_1), false);
        printf("_____________________\n");
        fflush(stdout);
    
        free(int_arr_ptr);
        int_arr_ptr = NULL;
        printf("freeing the array...\n");
        fflush(stdout);
        printf("________END_____________\n");
        fflush(stdout);
        ck_assert_int_eq(ptr_tree_base_int_1->size, 0);
    } END_TEST
    

    PrintTree功能

    bool printTree(TreeBase *tree){
    void *previous = NULL;
    int cnt_tasks = 0;
    if (!tree) {
        printf("PRINT: Cannot print empty tree base\n");
        fflush(stdout);
        return false;
    }
    /* set current to root of binary tree */
    TreeNode *current_node = tree->base;
    if (!(tree->base)) {
        printf("PRINT: Cannot print empty tree\n");
        fflush(stdout);
        return false;
    }
    StackNode *stack = NULL;
    while (true) {
        if(current_node) {
            push(&stack, current_node);
            current_node = current_node->left;
        } else {
            if (stack) {
                current_node = pop(&stack);
                if (cnt_tasks > 1) {
                    if (tree->comp(previous, current_node->value) != -1) {
                        printf("PRINTTREE: Invalid BST\n");
                        fflush(stdout);
                        assert(NULL);
                    }
                }
                previous = current_node->value;
                tree->print(current_node->value);
                cnt_tasks++;
                current_node = current_node->right;
            } else {
                return (cnt_tasks == tree->size);
            }
        }
    }
    

    }

    tree-&gt;打印功能

    void print_ints(void *p){
       printf("%d\n", *(int*)p);
       fflush(stdout);
    }
    

    示例输出

        FREETREE: Cant free empty tree
        !!!Next line has to be:"cannot free empty tree"
        FREETREE: Cant free empty tree
        FREETREE: Cant free empty tree
        !!!Next line has to be:"cannot print empty tree"
        PRINT: Cannot print empty tree
        PRINT: Cannot print empty tree
        _____________________
    

    这是很多代码,主要观点是!!!应该有一行但是有两行

        printf("PRINT: Cannot print empty tree\n");
        fflush(stdout);
        return false;
    

    ^^此行打印两次

    评论:什么是“宏”?这是来自API

    #define     ck_assert_int_eq(X, Y)   _ck_assert_int(X, ==, Y)
    

1 个答案:

答案 0 :(得分:1)

macro版本0.9.6中引入的ck_assert_int_eq Check unit testing framework定义为:

#define _ck_assert_int(X, O, Y) ck_assert_msg((X) O (Y), \
  "Assertion '"#X#O#Y"' failed: "#X"==%d, "#Y"==%d", X, Y) 
#define ck_assert_int_eq(X, Y) _ck_assert_int(X, ==, Y) 

可以看出,参数在宏定义中出现两次:一次用于实际的相等性检查((X) O (Y)部分),另一次作为ck_assert_msg(..., X, Y)的最后一个参数用于在发生故障时记录消息。查看代码的特定部分:

// should print cannot print empty tree
printf("!!!Next line has to be:\"cannot print empty tree\"\n");
fflush(stdout);
ck_assert_int_eq(printTree(ptr_tree_base_int_1), false);

C预处理器会相应地将宏扩展为等同于:

的代码
// should print cannot free empty tree
printf("!!!Next line has to be:\"cannot free empty tree\"\n");
fflush(stdout);
ck_assert_msg((printTree(ptr_tree_base_int_1)) == (false), 
  "Assertion '"#X#O#Y"' failed: "#X"==%d, "#Y"==%d", 
  printTree(ptr_tree_base_int_1), false);

printTree函数因此被调用两次,带有所有相关的副作用,包括两次打印行"PRINT: Cannot print empty tree"。 保护自己免受此类错误的一种方法是确保宏的参数没有可能的副作用。这可以通过将调用移到宏外的printTree来实现:

bool printTreeResult;
printTreeResult = printTree(ptr_tree_base_int_1);
ck_assert_int_eq(printTreeResult, false);

请注意,由于这种宏通常容易出错(正如您刚刚经历过的那样),ck_assert_int_eq的定义在版本0.9.9中得到了改进:

#define _ck_assert_int(X, OP, Y) do { \
  int _ck_x = (X); \
  int _ck_y = (Y); \
  ck_assert_msg(_ck_x OP _ck_y, \
    "Assertion '"#X#OP#Y"' failed: "#X"==%d, "#Y"==%d", _ck_x, _ck_y); \
} while (0)
#define ck_assert_int_eq(X, Y) _ck_assert_int(X, ==, Y)

相应地,解决重复输出行问题的另一种方法是将Check单元测试框架的安装升级到更新版本(即至少0.9.9),如果这是一个选项。