3

我编译以下main.c内容gcc main.c -Wl,--wrap=foo -lcmocka

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

#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <cmocka.h>

typedef struct ExampleStruct {
    int32_t foo;
    int32_t qux;
    void* bar;
} ExampleStruct;

ExampleStruct __wrap_foo(int32_t foo, int32_t qux, void* bar) {
    printf("bar after: %p\n", bar);
    return (ExampleStruct) {
        .foo = foo,
        .qux = qux,
        .bar = bar
    };
}

void test() {
    void* bar = "fef";
    printf("bar before: %p\n", bar);
    foo(1, 1, bar);
    assert_int_equal(2,2);
}

int main() {
    const struct CMUnitTest tests[] = {
        cmocka_unit_test(test),
    };

    return cmocka_run_group_tests_name("success_test", tests, NULL, NULL);
}

我得到以下输出:

[==========] Running 1 test(s).
[ RUN      ] test
bar before: 0x40087f
bar after: 0x40087f
[       OK ] test
[==========] 1 test(s) run.
[  PASSED  ] 1 test(s).

但是如果我添加一个新成员bazExampleStruct

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

#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <cmocka.h>

typedef struct ExampleStruct {
    int32_t foo;
    int32_t qux;
    int32_t baz;
    void* bar;
} ExampleStruct;

ExampleStruct __wrap_foo(int32_t foo, int32_t qux, int32_t baz, void* bar) {
    printf("bar after: %p\n", bar);
    return (ExampleStruct) {
        .foo = foo,
        .qux = qux,
        .baz = baz,
        .bar = bar
    };
}

void test() {
    void* bar = "fef";
    printf("bar before: %p\n", bar);
    foo(1, 1, 1, bar);
    assert_int_equal(2,2);
}

int main() {
    const struct CMUnitTest tests[] = {
        cmocka_unit_test(test),
    };

    return cmocka_run_group_tests_name("success_test", tests, NULL, NULL);
}

我得到以下输出:

[==========] Running 1 test(s).
[ RUN      ] test
bar before: 0x40086f
bar after: 0x7f3ff17cb2cd
[  ERROR   ] --- Test failed with exception: Segmentation fault(11)
[  FAILED  ] test
[==========] 1 test(s) run.
[  PASSED  ] 0 test(s).
[  FAILED  ] 1 test(s), listed below:
[  FAILED  ] test

如果我不使用包装函数,一切似乎都按预期工作。

更多细节

我正在使用 GNU ld 版本 2.27-44 运行 gcc 4.8.5

问题

为什么添加另一个成员会ExampleStruct导致分段错误?为什么在复制到's 参数bar时会改变值?__wrap_foo

4

1 回答 1

2

您需要为foo函数添加声明。目前foo(1, 1, 1, bar);将使用int foo(). 自 C99 以来,隐式声明无效,因此您应该能够打开更多警告以捕获此 ( -Wimplicit-function-declaration -Werror)。

隐式声明的函数接受你给它的参数(它实际上会匹配__wrap_foo,因为它int32_t是一个typedeffor int)并且会返回int,而不是ExampleStruct,所以你的程序将有未定义的行为

例子:

#include <assert.h>
#include <stdio.h>
#include <stdint.h>

typedef struct ExampleStruct {
    int32_t foo;
    int32_t qux;
    int32_t baz;
    void* bar;
} ExampleStruct;

// ** add this declaration **
ExampleStruct foo(int32_t foo, int32_t qux, int32_t baz, void* bar);

ExampleStruct __wrap_foo(int32_t foo, int32_t qux, int32_t baz, void* bar) {
    printf("bar after : %p\n", bar);
    return (ExampleStruct) {
        .foo = foo,
        .qux = qux,
        .baz = baz,
        .bar = bar
    };
}

int main() {
    void* bar = "fef";
    printf("bar before: %p\n", bar);
    foo(1, 1, 1, bar);
    assert(2 == 2);
}
于 2022-02-14T15:33:21.793 回答