很大的一个C工程,里面有N个C文件,请问,怎样调试某一个文件,而不是每次都是从主函数进去一层一层调

很大的一个C工程,里面有N个C文件,请问,怎样调试某一个文件,而不是每次都是从主函数进去一层一层调,第1张

你用的什么工具调试的,windows下VS系列的IDE都很方便,直接在你要调试的地方设置断点,运行的时候遇到断点就会中断,你就可以调试了,linux下用gdb一样的,使用b添加断点即可。

如果这个C文件里面的代码和其它文件关联比较小,也可以直接拿出来,单独建一个工程进行调试,如果和其它文件有关联,就比较麻烦了,如果单独拿出来测试,需要构造相应的变量、条件之类的,一般我们称之为打桩测试,如果整个程序是正常的,并且有测试用例能到达你的那个C文件,那还是整体调试比较方便。

tar cvzf ...楼主说到安装,其实linux下的安装包括两部分,一部分是文件拷贝,一部分是环境配置,楼主可通过脚本处理,同样你也可以用脚本处理压缩或者解压等 *** 作,写个shell吧,亲。最后祝楼主学习进步。

PHP打桩算法

打桩是一种用定制的函数替换链接库函数且不需重新编译的技术。甚至可用此技术替换系统调用(更确切地说,库函数包装系统调用)。可能的应用是沙盒、调试或性能优化库。为演示过程,此处给出一个简单库,以记录GNU/Linux中

malloc 调用次数。

/* _GNU_SOURCE is needed for RTLD_NEXT, GCC will not define it by default */

#define _GNU_SOURCE

#include <stdio.h>

#include <stdlib.h>

#include <dlfcn.h>

#include <stdint.h>

#include <inttypes.h>

 

staticuint32_t malloc_count = 0

staticuint64_t total = 0

 

voidsummary(){

    fprintf(stderr, "malloc called: %u times\n", count)

    fprintf(stderr, "total allocated memory: %"  PRIu64 " bytes\n", total)

}

 

void*malloc(size_tsize){

    staticvoid* (*real_malloc)(size_t) = NULL

    void*ptr = 0

 

    if(real_malloc == NULL){

        real_malloc = dlsym(RTLD_NEXT, "malloc")

        atexit(summary)

    }

 

    count++

    total += size

 

    returnreal_malloc(size)

}

打桩要在链接libc.so之前加载此库,这样我们的 malloc 实现就会在二进制文件执行时被链接。可通过设置 LD_PRELOAD

环境变量为我们想让链接器优先链接的全路径。这也能确保其他动态链接库的调用最终使用我们的 malloc

实现。因为我们的目标只是记录调用次数,不是真正地实现内存分配,所以我们仍需要调用“真正”的 malloc 。通过传递 RTLD_NEXT 伪处理程序到

dlsym,我们获得了指向下一个已加载的链接库中 malloc 事件的指针。第一次 malloc 调用 libc 的 malloc,当程序终止时,会调用由

atexit 注册的获取和 summary 函数。看GNU/Linxu中打桩行为(真的184次调用!):

$ gcc -shared -ldl -fPIC malloc_counter.c -o /tmp/libmcnt.so

$ export LD_PRELOAD="/tmp/libstr.so"

$ ps

PID TTY TIME CMD

2758 pts/2 00:00:00 bash

4371 pts/2 00:00:00 ps

malloc called: 184 times

total allocated memory: 302599 bytes

下面来看下PHP打桩算法在使用时出现的问题。

当构造测试用例的数据,是在函数内部被另一个外部函数所使用时,我们需要忽略外部函数所带来的影响。

需要进行“打桩”,举一个具体的例子

class DataGetter {

public:

...

bool Run()

...

private:

...

Client* m_ptr_client

...

}

.....

.....

bool DataGetter::Run() {

...

std::string data

bool ret = m_ptr_client->GetData(data)

...

}

....

....

比如要对run这个函数进行单元测试,它内部调用了ptr_client->GetData(data)的方法,它是通过tcp协议从服务端取数据到data里,测试run这个函数,必然要构造data。

如果不“打桩”,要测试的话,我们就需要再从服务端去构造数据,而且还可能收到其他因素的影响。

这时候“桩”就是很好的一种技术。

那如何去构造“桩”呢。

那么如何构造呢?

原理:利用c++ virtual的特性,改变m_ptr_client指针所指向的对象,重写一个“打桩”测试类。

当然,前提是GetData的定义本身是virtual的。

假设Client的定义如下

class Client {

......

public:

virtual bool GetData(std::string& data)

......

}

我们只需要重写Getdata的方法,并且当参数data被传进来时,我们可以返回特定的值。

这一套方法,google已经提供了很好的一套框架:gmock

下面介绍一下它的用法

#include "client.h" //被mock的类的头文件

#include// gmock 的头文件

class MockClient : public Client {

public:

MockClient():Client() {}

MOCK_METHOD1(GetData, bool(std::string&))

}

这里使用了一个宏MOCK_METHOD1

原形是MOCK_METHOD#1(#2, #3(#4) )

#1表示被mock的函数参数个数,#2表示被mock的函数名称,#3表示被mock的函数返回值,#4表示被mock的函数参数列表

这样,一个“桩”就“打”好了。

如何正确简便地使用

首先,要先改变m_ptr_client指向的对象,对于private的变量,在前一章有描述方法,

然后测试的时候,直接将 m_ptr_client = new

MockClient()即可,不过要记得释放它之前new的资源(如果有的话),不然就内存泄露了,哈哈

使用gmock的几个宏,用一个例子简单介绍下:

EXPECT_CALL( //mock被调用时,要发生的动作

*m_ptr_client, // 被mock的对象,看清楚,是对象,不是指针了

GetData(test::_) // 被mock的方法,参数为占位符

).Times(2) // 表示被调用2次

.WillOnce( 第一次调用

testing::SetArgReferee<0>(“test”), //设置第0个参数的值为“test”

testing::Return(true), //设置返回值为true

)

.WillOnce( 第二次调用

testing::SetArgReferee<0>(“test”), //设置第0个参数的值为“test”

testing::Return(false), //设置返回值为false

)

测试的原则,尽量不修改被测函数,覆盖函数的每一个分支,保证外部条件都是正确的。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/11716053.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-18
下一篇 2023-05-18

发表评论

登录后才能评论

评论列表(0条)

保存