创建易于管理的一个项目
我一般选择创建空项目并且创建源文件目录:
修改目标文件和中间文件目录:
输出目录:$(SolutionDir)bin\$(Platform)\$(Configuration)\
中间目录:$(SolutionDir)temp\$(Platform)\$(Configuration)\$(ProjectName)\
这样输出文件和中间文件就和源文件分开了。
在编译Release版本时候会有下面的问题:
修改:
调试方法
调试可以帮助我们有效的观察程序、分析程序,当然最重要的就是解决程序的bug、性能瓶颈等。
我自认为调试的技巧就是跟踪数据的变化,一般只要我们找到数据的异常变化点就能定位bug。
下面列举一些常用的调试方法
我们拿一个简单的程序当例子看一下我们在vs2017中有哪些调试手段:
#include <stdio.h>
int main()
{
int total = 0;
for (int i = 0; i < 30; ++i)
{
total += i;
}
printf("total = %d\n", total);
return 0;
}
当我们像知道循环到i==10
时候total的值是什么。
1、打印数据来调试
最简单的也是最先接触到的肯定是printf
输出信息了:
#include <stdio.h>
int main()
{
int total = 0;
for (int i = 0; i < 30; ++i)
{
total += i;
if (10 == i)
{
printf("debug: total = %d\n", total);
}
}
printf("total = %d\n", total);
return 0;
}
当然我们可以用宏把我们的调试代码和代码隔离开:
#include <stdio.h>
int main()
{
int total = 0;
for (int i = 0; i < 30; ++i)
{
total += i;
#ifdef _DEBUG
if (10 == i)
{
printf("debug: total = %d\n", total);
}
#endif // _DEBUG
}
printf("total = %d\n", total);
return 0;
}
2、普通断点
我们还可以使用断点来代替这段代码:
我们下完断点之后点击运行,可以发现它在第一次执行到total += i;
的时候停下来了,但是不是我们想要的i为10,我们可以点击继续或者下一步直到i为10。
3、条件断点
i为10我们也许还能有耐心的慢慢点,但是如果要的i值很大的时候该怎么办,一开始用printf
输出信息我们是放在了if语句中的,所以类似的我们可以使用条件断点:
可以看到断点样子变了。
这样直接停下来就是i为10的时候。
4、条件跟踪
我们还可以给我们的条件添加操作,一些常用到的调试信息都可以通过$xxx
来表示:
断点样子又变了,并且我们可以选择是否在断点处停下。
5、添加监视
添加监视其实大多数时候和我们的局部变量显示的变量是差不多的。
当我们函数返回一个指针,并且这指针是一个数组的退化:
#include <stdio.h>
#include <malloc.h>
int* fun()
{
int *p = (int*)malloc(sizeof(int) * 4);
for (int i = 0; i < 4; ++i)
{
p[i] = i;
}
return p;
}
int main()
{
int *p = fun();
free(p);
return 0;
}
我们发现只能看到一个值,我们可以使用快速监视:
6、单步调试
当我们断点断在一个函数的时候:
我们有两个选择:
- 逐语句会进入函数内部
- 逐过程会直接执行完整个函数
第三个按钮是跳出,当我们进入fun后点跳出,会直接运行到这个函数结束,我们还能看到我们的p是垃圾值,也就是赋值语句还没执行:
创建一个linux项目
先下载相关组件:
创建对应项目:
添加linux(此处使用的虚拟机):
出现错误:
linux安装一下g++
再试一下就好了:
编写cpp文件,可以发现已经有提示了:
找个线程互斥的例子:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <semaphore.h>
sem_t sem;
void printer(const char *str)
{
sem_wait(&sem);
while (*str)
{
putchar(*str);
fflush(stdout);
str++;
sleep(1);
}
sem_post(&sem);
}
void *thread_fun1(void *arg)
{
const char *str1 = "hello";
printer(str1);
return NULL;
}
void *thread_fun2(void *arg)
{
const char *str2 = "world";
printer(str2);
return NULL;
}
int main(void)
{
pthread_t tid1, tid2;
sem_init(&sem, 0, 1);
pthread_create(&tid1, NULL, thread_fun1, NULL);
pthread_create(&tid2, NULL, thread_fun2, NULL);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
return 0;
}
写上熟悉的-lpthread
:
编译没问题,点击运行(Debug):
安装一下:
再次debug: