Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.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++ 如何打破GMU r C++;_C++_Unit Testing - Fatal编程技术网

C++ 如何打破GMU r C++;

C++ 如何打破GMU r C++;,c++,unit-testing,C++,Unit Testing,这可能是一个奇怪的问题,但我正试图找到一种方法来打破gmtime\r函数。我正在为这段代码编写一个测试,但是我找不到一个不包括将ptr或dates设置为NULL的else语句 int main() { time_t ptr; // Actual storage for time_t struct tm dates; // Actual storage for struct tm time(&ptr); // Pointer to a time_t if(g

这可能是一个奇怪的问题,但我正试图找到一种方法来打破
gmtime\r
函数。我正在为这段代码编写一个测试,但是我找不到一个不包括将
ptr
dates
设置为
NULL
的else语句

int main() {
    time_t ptr; // Actual storage for time_t
    struct tm dates; // Actual storage for struct tm
    time(&ptr); // Pointer to a time_t
    if(gmtime_r(&ptr, &dates)) { // Pointer to a time_t, pointer to a
        size_t a = 10;
    }
    else
    {
        size_t a = 20; //<-- trying to reach this else statement
    }
return 0;
}
intmain(){
time\u t ptr;//time\u t的实际存储
struct tm dates;//struct tm的实际存储
时间(&ptr);//指向时间的指针
if(gmtime\r(&ptr,&dates)){//指向时间的指针,指向
尺寸a=10;
}
其他的
{

size\u t a=20;//要准确回答您的问题,我们需要了解您用于构建项目的实现

通常,标准的头文件(比如)都有公共源文件,因此您可以自己搜索失败的可能性

对于glibc,我到兔子洞里举了个例子。 (见资料来源)

time/gmtime.c
中,我们可以看到gmtime\r是\uu gmtime\r的一个弱别名,它直接返回\uu tz\u convert

time/txset.c
中,我们看到uu-tz_-convert只能在u-offtime函数失败时返回NULL(返回0)

最后,在
time/offtime.c
中,我们看到:

  tp->tm_year = y - 1900;
  if (tp->tm_year != y - 1900)
    {
      /* The year cannot be represented due to overflow.  */
      __set_errno (EOVERFLOW);
      return 0;
    }
这表明了一个很好的线索,我们可以让它失败。 你可以用一个简短的程序来验证你的想法

e、 g

在我的例子中,简单地提供一个大的正时间就可以了,因为代码使用整数很多年,但是时间是64位的值(在我的系统上),我可以有比int(在我的系统上)所能代表的更多的年


当然,您可以立即执行示例测试程序,而无需查看源代码。但是这样做不是更有趣吗?:p

使用
LD_PRELOAD
技巧是可能的。我不会深入解释它,因为这可以在谷歌中看到,也可以在短搜索中看到

我将展示我是如何在C中实现它的,因为它对C用户也是有效的:

让我们使用另一个C文件并将其命名为trick.C:

我使用命令行
gcc main.c-o main-ldl
编译它

然后,我使用以下命令来运行可执行文件,其中技巧共享对象替换
gmtime\u r()
LD\u PRELOAD=./main

您应该从
main()
调用
\u fail\u gmtime\u r()
\u pass\u gmtime\u r()
,以实现相同的效果


我没有深入解释,但如果您喜欢,我可以在这里进一步解释所有内容。

作为旁注,我认为建议使用
ptr=time(NULL);
,它确保了永远不会失败,而不是指针变量。这是一个非常好的答案,但将该示例程序的代码作为代码块而不是屏幕截图发布会更有帮助。但是,顺便说一句,我无法展示这一点,我使用了arch。:c——更严肃的一点是,我想清楚地说明暗示整个过程是,我只是直观地“捕获”了它的屏幕。遗憾的是,这些文件都已被删除,因此我无法将其编辑回文本样本/
#define _GNU_SOURCE

#include <dlfcn.h>
#include <time.h>

typedef struct tm * (*gmtime_r_t)(const time_t *, struct tm *);

static int __fail = 0;

void __fail_gmtime_r() { __fail = 1; }
void __pass_gmtime_r() { __fail = 0; }

struct tm *gmtime_r(const time_t *timep, struct tm *result)
{
    if (__fail) { return NULL; }

    return ((gmtime_r_t)dlsym(RTLD_NEXT, "gmtime_r"))(timep, result);
}
#define _GNU_SOURCE

#include <dlfcn.h>
#include <time.h>
#include <stdio.h>

typedef void (*__fail_gmtime_r_t)();
typedef void (*__pass_gmtime_r_t)();

int main()
{
    __fail_gmtime_r_t __fail_gmtime_r = dlsym(RTLD_DEFAULT, "__fail_gmtime_r");
    __pass_gmtime_r_t __pass_gmtime_r = dlsym(RTLD_DEFAULT, "__pass_gmtime_r");

    time_t ptr;
    time(&ptr);

    struct tm dates;

    printf(gmtime_r(&ptr, &dates) ? "OK\n" : "FAIL\n");

    __fail_gmtime_r();
    printf(gmtime_r(&ptr, &dates) ? "OK\n" : "FAIL\n");

    __pass_gmtime_r();
    printf(gmtime_r(&ptr, &dates) ? "OK\n" : "FAIL\n");

    return 0;
}