为什么要单独写个纪实呢?因为感觉实践过程太尼玛坑爹了,处处中招,各种触发警报,各种又红又黄的提示,都看不下去了,想想也是,这是我的第一次应该是正式的项目工程了,要会用github、git进行版本管理,还有用宇宙第一IDE进行测试、性能分析等等,所有的这种工程实践都是第一次去做,难免磕磕碰碰,这些经历的记录还是非常有意义的。
今天第一次在github上建仓库,我的第一个仓库——Personal_Suduku。
首先是配置我的个人信息,虽然账号是去年暑假创建的,不过没怎么配置,空空如也。这个比较简单,看一般的教程就会,不过选哪个邮箱作为我的登陆邮箱好头疼,因为邮箱有点多。。。头像简单,这个早就准备好了,虽然有点丑~
然后是在本地用git命令clone我的仓库到指定文件夹,原本想先在本地创建仓库,再推到github上,后来感觉有点麻烦,对小白不友好就放弃了。当然在这个过程之前,要先配置SSH,先在Git Bash中输入ssh
进行判断是否安装了SSH,再输入ssh-keygen -t rsa -C "github登陆邮箱"
指定RSA算法生成密钥,然后三个回车即可,注意留心它给出的.ssh
文件夹的位置,不同电脑位置有些不同,然后打开.ssh
文件夹(注意这个是隐藏文件夹),找到其中的id_rsa.pub
文件,用vscode/sublime text等编辑器打开,尽量别用windows自带的记事本,复制其中的内容并添加到Github上的SSH key上(点击头像旁的小三角,找到Settings
并点击,进入个人信息配置界面,再找到SSH and GPG keys
并点击,进入后再点New SSH key
,Title
里输入你之前的那个邮箱,Key
里粘贴id_rsa.pub
里复制的内容)。添加SSH key成功后再次打开Git Bash输入ssh -T [email protected]
它会问你Are you sure you want to continue connecting (yes/no)?
输入yes
即可,然后等待一段时间出现Hi xxx! You've successfully authenticated, but GitHub does not provide shell access.
就说明成功了。
接下来就可以从Github上clone仓库了。先去gihub上进入需要clone的项目仓库界面,旁边有个绿色的Clone or download
点击并Clone with SSH
复制内容然后在Git Bash中输入git clone [email protected]:xxx/xxxx.git
其中[email protected]:xxx/xxxx.git
就是刚才复制的内容。然后等待即可。你也可以指定本地保存的仓库位置,不过需要提前使用cd
命令进入指定文件夹,然后输入上面的git clone命令就可以了。
然后说说Visual Studio 2017里的坑,建议大家先下Gihub插件并输登陆。我在VS里添加了一些文件夹,然后想试试能不能commit,结果报错
Git failed with a fatal error.
error:open(".vs/Personal_Suduku/v15/Browse.VC.opendb"):Permission denied
fatal:Unable to process path .vs/Personal_Suduku/v15/Browse.VC.opendb
出现权限错误,想了想,好像没有将新建的文件提交到仓库中,我使用git status
命令看了看,结果提示
Untracked files:
(use "git add ..." to include in what will be committed)
.vs/
src/
nothing added to commit but untracked files present (use "git add" to track)
意思就是.vs/
和src/
两个文件没有被跟踪,即没有被添加到仓库中。那么输入两条命令git add .vs/
和git add src/
添加这两个文件。
再取VS里发现可以commit了,然后我们可以同时推送到github上。
今天主要分析了一下程序结构
主体结构
在分析指令这一块应该还有个箭头指到输出,因为会有错误输入的情况,要输出警告。
今天又有警告。。。
fatal: pathspec '.vs\Personal_Suduku\v15\Browse.VC.opendb' did not match any files
又是和第一次一样的警告,emmmm,似乎没有完全搞懂这个问题,尴尬,在VS里有个error open
那就进命令行并关闭VS,然后我直接git add Browse.VC.opendb
又报错,再试git add .vs\Personal_Suduku\v15\Browse.VC.opendb
又报错,就是上面那个,咦,看看提示,did not match any files
,那就试试git add .vs\Personal_Suduku\v15\
,可以了。难道每次都有全新的Browse.VC.opendb
产生吗?
用VS直接推送虽然爽歪歪,但是还是不够熟练,有好多推送和备注都没对上,我似乎之前几次都是临时保留,然后推送的都是上次的缓存。还要多用用才行,还有,那个版本回退是什么情况?目前没用过,很好奇具体操作及效果~
晚上写了生成终局的部分,算法没有用多高大上的,就是暴力回溯搜索,有点小bug,为啥只能输出一份终局?后面全乱码了???但是我个人觉得算法的思想毫无问题啊,应该是我实现时有地方搞错了。
算了我就是觉得暴力回溯没问题,bug再调调,现在讲一下算法原理吧,这个绝对没问题。
数独的规则应该都知道了,横竖1\~9不能有重复,然后每个3×3的小九宫格内又是1\~9不能有重复,总共是9×9的大九宫格。
我们看一下这个规则,会发现一个规律,就是第一行有数x后不能再有x,它一定会依次出现在后面的行,同理列也一样,然后其他数也是这样。那么我们如果按数字顺序在第一个小方格内填入1,然后再在第二行某个格填入1,依次类推直到填完9种数,到这里有人会说这样迟早会产生冲突,出现不符合规则的局面,没错,的确会这样,那么我们就从试不了的地方开始回溯,换个数继续试,直到满足位置,这里有时候会回溯好几步才能成功,不过计算机比较快,尤其是用递归实现起来还是相当快的了。
用伪代码描述:
function Backtracking_Search(i, j) //i,j表示的是大九宫格里的(i, j)格
{
if 已生成的终局数 >= 要求生成的终局数:
return;
if 生成一个新终局: //检查生成新终局的便捷办法就是判断边界条件
{ //当格子的位置移出9×9的大九宫格外说明就有新终局了
已生成的终局数++;
输出新生成的终局; //或者先存起来一起输出
return;
}
if 到了一行的最末: //这个看你是怎么搜索了,我是按行的,也可以按列
{
换行到下一行开头; //我的就是i++;j=1;换列就是i=1;j++;
}
for num from 1 to 9:
{
if 已生成的终局数 >= 要求生成的终局数:
return;
if 准备填入(i,j)格的数num满足数独规则:
{
将num赋值给(i,j)格;
Backtracking_Search(i, j);//满足条件就继续递归下去
}
}
(i, j)格重置为0; //说明填什么数字都不满足数独规则,要开始回溯,这个位置要重置为0
}
这个算法的出口就是你要生成多少终局,如果不限制的话,让它穷举完。。。应该是6670903752021072936960种,具体介绍在这篇论文Enumerating possible Sudoku grids。
刚把生成终局的bug搞定,原来是递归时传入的一个参数输错了。。。它们的类型一样,命名也像,所以就。。。我靠,智障如我!改正之后非常nice,输出还是比较快的。不过还是有不少优化空间,当然核心算法就要改动不少了,目前是没有什么比较好的思路,推倒重来有点。。。看时间吧。
输出借鉴了网上的一个方案,生成的终局不要立刻输出,先存到数组里,然后再一起输出到文件里,这样会比较快,emmmmm,好像很有道理的样子,然后有一次存终局的数组开的太大,好像有20亿级?还是200亿级?然后又是运行崩溃,报错内容忘记截了,这块有点脑残了,明明是可以算出来需要多少的,总共9×9数独,加上每个数字后有空格或回车即 81×2=162 81 × 2 = 162 ,然后每份数独之间空行,再加1,即163,然后压力测试要求有一百万份数独,就是 163×106 163 × 10 6 。后来运行OK!
这里提醒各位不要试图用电脑自带的记事本打开这一百万的数独文件,我看了下大小有164MB。
推荐用vscode、sublime text、vim之类的编辑器开,我因为也在用vscode编程,所以就用vscode开了,基本上秒开,顺带安利一下vscode!
再提醒一个习惯,就是使用构造函数初始化一下创建的对象!析构函数好像没什么用,反正目前没用过,以后说不定。
最最最严重的是VS又给我报了一个诡异的错误,见下:
严重性 | 代码 | 说明 | 项目 | 文件 | 行 | 禁止显示状态 |
---|---|---|---|---|---|---|
错误 | C3861 | “time”: 找不到标识符 | Project_Sudoku | …\personal_suduku\project_sudoku\project_sudoku\project_sudoku.cpp | 16 |
我一脸懵逼,原本想用time函数给我的程序计个时,结果跟我说time找不到了???看了看头文件,#include
也有啊,又看了看命名空间也没毛病啊,再看看项目里也没有和这个头文件命名冲突的。。。莫名其妙的错误。。。而且我在编辑时代码智能提示里也可以给出这个函数啊,是找得到的啊。
昨天的那个time函数bug解决了,修改很简单,我把各个文件中的#include"stdafx.h"
头文件移到顶行,再把#include
移到了#include
这些头文件的下面,然后就编译通过了。。。
看的这篇博文error C2065:未声明的标识符错误,大意即不仅要引入相关的头文件,其位置也要放正确。
在网上这个C3861错误或相关的错误问题基本上的解决办法就这样:
1. 是否引用了正确的头文件。
2. 是否引用了正确的命名空间。
3. 是否存在引用的头文件与工程内创建的文件产生命名冲突。
4. 引用的头文件的位置顺序是否正确
这bug真是太迷了。。。还好顺利解决了!后来看到Visual Studio的官方文档里就有简单的提到。。。Visual Studio 中的 C++ 入门
若要添加 iostream 标头,请在 #include "stdafx.h" 后输入此代码:
#include
using namespace std;
看一下100万的时间,emmmmmmmm,感觉还行!虽然大佬的比我快一个数量级。。。
下午初试了一下代码分析,因为要求里说提交的代码要经过代码分析工具的分析并消除所有警告。
我给项目配置的规则集是Microsoft 本机建议规则,毕竟是官方文档列举的标准规则集,看了一下描述还行就用了。
在勾选生成时启用C/C++代码分析后马上试了试,然后一下给我爆出25条警告。。。
主要有一下几种(选了些代表,未全列):
警告代码 | 警告说明 | 我的解决策略 |
---|---|---|
C26494 | Variable ‘end’ is uninitialized. Always initialize an object (type.5: http://go.microsoft.com/fwlink/p/?LinkID=620421). | 因为是变量没有初始化,所以初始化一下即可 |
C26495 | Variable ‘Sudoku::board’ is uninitialized. Always initialize a member variable (type.6: http://go.microsoft.com/fwlink/p/?LinkID=620422). | 又是变量没有初始化,不过这条警告是指向我的类的构造函数,当然也能理解,是成员变量没有初始化,基本上就初始化一下就好,使用的memset()初始化,因为用循环全遍历还是报警告 |
C26439 | This kind of function may not throw. Declare it ‘noexcept’ (f.6: http://go.microsoft.com/fwlink/?linkid=853927). | 可能不会引发此类型的函数,将其声明为”noexcept”。emmmmm,这个有点迷啊,官方文档是这么说的,自己看吧C26439 SPECIAL_NOEXCEPT,那就按文档里说的显示声明noexcept(true) 即可 |
C26485 | Expression ‘this->board’: No array to pointer decay (bounds.3: http://go.microsoft.com/fwlink/p/?LinkID=620415). | 无数组到指针的衰减(bounds.3)。。。要炸啊,我C26495用memset()改后就蹦出这个, |
C26496 | The variable ‘row’ is assigned only once, mark it as const (con.4: https://go.microsoft.com/fwlink/p/?LinkID=784969). | 这个变量就用过一次,要标记为常量,加个const |
C26451 | Arithmetic overflow: Using operator ‘+’ on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator ‘+’ to avoid overflow (io.2: https://go.microsoft.com/fwlink/?linkid=864598). | 应用算术运算后进行转换。调用操作符之前将值转换为更广泛的类型以避免溢出。所以改成了const long OutNum = 163 * OutputNum + 5 ,const 是因为这个数就用了一次,要用常量 |
C26409 | Avoid calling new and delete explicitly, use std::make_unique instead (r.11: http://go.microsoft.com/fwlink/?linkid=845485). | 避免显式调用 new 和 delete,请改用 std::make_unique (r.11) |
C6386 | 写入到“this->OutArray”时缓冲区溢出: 可写大小为“OutNum*1”个字节,但可能写入了“8”个字节。 | |
C26481 | Don’t use pointer arithmetic. Use span instead (bounds.1: http://go.microsoft.com/fwlink/p/?LinkID=620413). | 请勿使用指针算法。改用范围(bounds.1)。 |
C26401 | Do not delete a raw pointer that is not an owner (i.11: http://go.microsoft.com/fwlink/?linkid=845474). | 请勿删除不是所有者的原始指针(i.11)。用个delete[] this->OutArray 出错了 |
C26409 | Avoid calling new and delete explicitly, use std::make_unique instead (r.11: http://go.microsoft.com/fwlink/?linkid=845485). | 避免显式调用 new 和 delete,请改用 std::make_unique (r.11)。这条警告是紧接这上面的 |
C26482 | Only index into arrays using constant expressions (bounds.2: http://go.microsoft.com/fwlink/p/?LinkID=620414). | 只使用常量表达式在数组中编制索引(bounds.2)。 |
这些警告搞死人了,还在消除警告ing,等上面的警告都有应对策略时说明我基本上是搞定了。不行,要吐了,太恶心了!
这是一个不幸的消息,也不知道是不是我修改警告时没注意还是我添加输入选择后的原因,我程序的生成终局功能的耗时突然增加了好几个数量级,原本半分钟内跑出100万然而现在1万都要1分钟了,很不开心,昨天还辛辛苦苦的消除警告,今天有忙着改输入选择,诶。。。
这里就体现Git的好处了,可以进行版本回退,不像以前是手工重新码代码,现在是一步回退,不过不知道为什么我的VS不能进行回退了,推送还没试过,因为昨天晚上更新了一下VS,可能是某个地方又出问题了吧。回退时VS给我的警告是
Git failed with a fatal error.
revert failed
emmmm,莫名其妙的。看网上教程也没弄好,于是直接用Git Bash输命令行指令了。然后顺利回退。
具体版本回退操作是这样的:先输入git reflog
查看历史记录,我的就在上一版,所以再输git reset --hard HEAD^
即可,你还可以再次输入git reflog
看看,它会显示你当前是版本回退的。
回退后赶紧试了试加了输入选择会不会影响程序运行时间,结果还行,就增加了1~2秒,还算能接受,说明并不是我输入选择部分的毛病,那就应该是加了代码分析的原因了,为了消除警告改动了一部分,接下来只好一步步测试了,光消除警告还不行,不能影响时间,这个很关键。
新的编译错误:
错误代码 | 错误说明 |
---|---|
C2061 | 语法错误: 标识符“Input” |
C2061 | 语法错误: 标识符“fstream” |
C2660 | “Sudoku::Straregy_S”: 函数不接受 1 个参数 |
C2660 | “Input::Get_Board”: 函数不接受 2 个参数 |
看了下网上的方法Error C2061:语法错误,头文件重复包含的错误,之前新建工程时VS就有提示,那个#include"stdafx.h"
头文件就是用来处理这种情况的,结果我一直没弄明白到底要干嘛,这次明白了,意思就是把你所有要用到的头文件全部放在#include"stdafx.h"
里,其它文件只要引用#include"stdafx.h"
这一个头文件就可以了。这么处理后发现第二行的那个错误还在,鼠标一放在fstream
上就懂了,赶紧在报错的文件加上using namespace std;
忘记加命名空间了。然后再编译上面的错误就消失了!
零代版本
解题的一个bug把我吓坏了,后来发现==
写成=
了,这种错误我也是醉醉的了。。。
今天终于把零代版本搞好了,之后就可以搞搞优化了,进程基本上已完成一半了感觉。今天下午写选择输入部分,晚上搞解题部分,有点累啊!之后优化也挺头疼,今天心情最不好的就是把版本回退了,为什么消除警告把耗时增加了?没搞懂到底是哪一块的问题。。。
先贴一张零代版本的测试图片。
这次就简单小测下,错误指令也能发现就不贴图了,总体来说就是时间问题了,这个与算法效率有关,输入输出也要看看。
解题部分用的也是回溯,就是把生成终局部分的回溯算法简单的做个小改动,基本原理没有变。输入选择部分主要用正则表达式进行格式匹配,如匹配数字的,我用的是^\\+?[1-9][0-9]*$
,输入选择部分写起来也挺头疼。具体的今天就不讲了,之后再更。
今天看了看Google C++风格指南,感觉自己的代码风格还要进一步修改,主要是有些风格习惯一时难以接受,不过仔细想想,有些风格规范还是有些道理,就是看着不爽。给代码定下风格还是花了不少时间,有的地方好纠结。原本打算今天搞单元测试的,诶,有没空了,单元测试好难的样子。。。
今天基本上修正完了不少代码的风格问题,然后就推送了,结果VS报错,后来进Git Bash使用git push origin master
命令,发现一样报错:
$ git push origin master
To github.com:InspAlgo/Personal_Suduku.git
! [rejected] master -> master (non-fast-forward)
error: failed to push some refs to '[email protected]:InspAlgo/Personal_Suduku.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
难道要先git pull
一下?结果又报错:
$ git pull
error: Your local changes to the following files would be overwritten by merge:
Project_Sudoku/.vs/Project_Sudoku/v15/.suo
Project_Sudoku/.vs/Project_Sudoku/v15/Browse.VC.db
Please commit your changes or stash them before you merge.
Aborting
emmmm,好像是之前版本回退造成的错误,因为是在本地进行的版本回退,GiHub上没有修改,于是只好进行强制推送git push -f origin master
,顺利推送,老师要是看commit的话看到这个我也无所谓了,版本回退过一次很正常嘛233333333
再做一次代码分析时又给我一个错误报告,编号BK1506 No such file or dire
,看网上教程,点击项目
->属性
->C/C++
->启用浏览信息
->否
,然后就好了没错误报告了,还有神奇的一点是现在的警告少了,竟然只有一个。
警告代码 | 警告说明 |
---|---|
C6319 | 在所测试的表达式中使用了逗号运算符,导致左侧的参数在无副作用时被忽略。 |
那一行是这样的for (int row = 1, col=1; row <= 9, col<=9; row++, col++)
于是查了一下文档C6319 ,原来要改成这样for (int row = 1, col=1; (row <= 9) && (col <= 9); row++, col++)
,在运行一下代码分析,竟然没有警告了,开心23333333,不过为什么上个星期天会有那么多的警告。。。
装企业版我能说是为了自动生成函数关系图吗,这个在体系结构
里有
主要还是看官网介绍好多测试及分析功能只有企业版有,然后一激动就换版本。。。
看了看性能分析,主要步骤为调试
->性能查看器
->性能向导
->CPU采样
,然后结果见下图:
通过性能分析图可以看出来我的检查函数占比较多,因为是暴力回溯所以每一步都要判断是否有重复、不符合规则的数字出现,而每次判断都要用循环遍历,这个就很耗时了,我是已经作了优化的,将横竖分别循环判断改成了同时循环判断,emm,没想到还是比较耗时间。还有一种方法就是加个位置记录,具体方法是这样,比如num_row[num][i]
代表数字num
在第i
行是否有出现,同理num_col[num][j]
代表数字num
在第j
列是否有出现,num_box[[num][row][col]
代表数字num
是否在第[row][col]
小九宫格上有出现。这样就不需要用循环判断了,填数字了就赋值为false
,刚开始没数字时是赋值为true
的。
然后试验了一下
如下图可以看出C策略函数的检查降到800的量级,之前还是4000的量级
这次改进还是有效果的,连检查函数我都删掉了,因为这种写法的话判断语句就太短了。不过需要注意的就是在合适的位置还原为true
。
然后发现一个问题就是输出到文本时间很不稳定,最好是0.6s,但经常在2s波动,是一起以文件流的形式输出到文本啊,emmmm,这一块还要优化,不过还没有比较好的思路,看有的人是0.5s量级,emmm,要是能把程序的输出总时间稳定在3s内估计对我来说就很不错了。
周五下午看了一下仓库,天哪,都1.5G了,不应该是几Kb的代码吗,怎么膨胀成这个样子了?就说推送时间怎么那么长,原来压缩了都有上百MB了。后来一看是VS的一些项目文件搞的鬼,然后我每次都git add .
全跟踪了,然后每次提交都会copy一下你的当前版本,结果就是滚雪球越滚越大。于是照着网上是教程取消跟踪部分文件,那些文件放在本地就好了,毕竟是VS需要的,虽然也可以删的,然后每次推送只要推你的代码就好。
首先给.gitignore
更改配置,将不需要跟踪的文件或文件夹添加进去,具体方法可以看这篇文章Git 中忽略某些文件或者文件夹。
然后就是删除已跟踪文件,也即是移出版本控制,但不是真正的删除文件。用的指令是git rm -r --cached "xxxxx"
,具体方法可以看这篇博文git如何移除某文件夹的版本控制,不过我忘了当时具体是怎么操作的了,感觉似乎当时并不是这样操作的,有点点区别。
再使用git ls-files
查看当前跟踪的文件,是不是你需要的呢?
如果是就可以git push
了,这样GitHub上也会删除你取消跟踪的文件,而且会发现分分钟秒推送啊,瞬间感觉世界清爽起来了!
这是一个非常重要的环节,看了好多天还是不会,微软的文档emmmmm,感觉自己没救了,连官方文档都读不懂了,郁闷。。。但这个环节还是要尽快完成,不能再拖了,只好硬着头皮上了。
在文件
选新建项目
,然后是Visual C++
中的测试
,选择本机单元测试项目
,下面的解决方案
一栏勾选添加到解决项目
,名称就自拟了。
先试了一下对输入单元的测试,结果一运行就有问题,一下子来4个
我先看了一下第一个警告LNK4075
一查,似乎忘记把Release
模式改回Debug
模式了,在微软的文档中好像看过说单元测试需要在Debug
模式下进行。然后改了一下,错误也就换了一下。。。(注:单元测试的确是要在Debug
模式下进行,LINK4075
的警告是对的)
什么鬼链接错误,大概又是头文件问题吧,然后在单元测试的头文件stdafx.h
中加了下面代码
#include
#include "../Project_Sudoku/input_control.h"
#include "../Project_Sudoku/sudoku.h"
然后错误又变了。。。
第二次的错误应该是头文件问题,但是这第三个错误又是头文件问题,emmmm,让我冷静一下。。。这C2061
以前遇过,就是头文件重复包含,需要全部加载到#include "stdafx.h"
文件中。
好吧,我怕了你了,我把sudoku.h
中的这个改掉,结果。。。
又是这个错误,又回去了。。。
然后仔细的看了下微软的文档说明,有这么一句话未链接的对象文件或包含符号定义的库。 在 Visual Studio 中,验证包含定义源代码文件是生成,分别链接为项目的一部分。 在命令行中,验证编译时包含定义的源文件,并且所生成对象文件包含在要链接的文件列表。意思就是光有头文件不行,还要知道源文件在哪里。。。再看看我的,用来是忘记加
#include "../Project_Sudoku/input_control.cpp"
#include "../Project_Sudoku/sudoku.cpp"
然后再一运行,终于没有错误了。。。
也就是在单元测试源文件中加上
#include "../Project_Sudoku/input_control.h"
#include "../Project_Sudoku/sudoku.h"
#include "../Project_Sudoku/input_control.cpp"
#include "../Project_Sudoku/sudoku.cpp"
单元测试的结果也出来了,未通过测试。。。什么鬼。。。
看了一下说明A 64-bit test cannot run in a 32-bit process. Specify platform as X64 to force test run in X64 mode on X64 machine.
64位测试不能在32位进程中运行。指定平台为 X64, 以强制在 X64 机器上 X64 模式下进行测试运行。emmmm,我生成的是64位程序啊?
后来在配置管理器把平台由x64
换成Win32
就好了。
再一运行,终于第一次成功通过测试2333333,开心!
今天发现了一个VS里的命令行陷阱,被小坑了一下,原本改命令行参数读入数独题求解,发现时间怎么搞得和生成100万的一样了?再一看生成文件,咦?怎么是生成100万的文件了?我明明是要解题的啊,再看看配置属性
的调试
里的命令行参数,是读题模式啊,emmmm,无疑中点了一下配置,原来Debug
和Release
模式的命令行参数是分开设置的。。。
之前在在进行代码覆盖率分析时它总说我无结果,然后看了一下错误列表的显示情况
无法显示用于以下二进制文件的方法:“xxx\Personal_Suduku\Project_Sudoku\x64\Release\sudoku.exe”
调用方信息不可用,原因如下:
仅支持在 x86 体系结构上运行的二进制文件。
未生成 .pdb 文件。请在链接器中启用 /DEBUG 选项。
再在网上查了一下,其实卡在这里好久了,嗯,今天终于搞定了
首先要改链接器调试输出信息设置,在生成调试信息
那选择生成经过优化以共享和发布的调试信息(/DEBUG:FULL)
然后我把单元测试项目也这样改了。
再就是配置管理器,因为上面的错误信息里说了要在x86的,所以改成Debug Win32
,为什么不是选x86
呢?emmmm,我能说是靠感觉选Win32
吗。。。之前好像也有看过Win32
肯定是32位的,然而AMD和Intel在x86则不一样。
然后单元测试项目也这样改了。
再运行代码覆盖率分析,可以了!
还是无法生成二进制文件?
1. 在项目属性页面,把平台选项改成Win32
,同时别忘改生成调试信息
,单元测试的和工程的都改。
2. 可能是项目配置问题,重新新建一个项目,再按照上述方法改动。
达到80%了,应该够了,也不追求百分之百了,我觉得我目前是办不到。
磕磕绊绊有十余天了,中途遇到了各种奇奇怪怪的bug,好迷啊,真的是感觉走了不少弯路,感觉是一个人在披荆斩棘,没有任何人帮助,没有交流,全是一个人自学,看博客、看官方文档。。。也参考了一位北航的学长的项目,这里也是非常感谢他带给我的灵感,有一种高人指点的感觉,从他那里也学到了不少。看文档是最痛苦的事了,因为微软的官方文档真的是言简意赅,一笔带过的感觉,有的时候还没有介绍。。。有的错误文档上找不到、博客也找不到,最是痛苦,没有任何改正方向,也不知道自己是怎么过来的。。。
个人觉得搞个人项目是好的,但是真的缺少指导,老师只负责布置任务,感觉你们什么都会的样子,然后什么都没有教。。。最起码安排一点时间答疑啊,组织大家把自己遇到的问题公布出来,一起讨论,然而什么都没有,或者安排助教建个群答疑啥的也好啊。。。那个教学软件也没有高效的利用起来,大家基本上没有什么讨论。。。老师应该演示一下要求里的代码分析、性能分析、单元测试、代码覆盖率分析,也不一定非要这个项目的,就是简单的实验性演示就好,至少自己就不会那么迷。。。当然什么都不教的确对我们是一种磨砺,因为未来的很多困难都是没有人给你演示的,必须要自己独立解决,要靠自己的力量。。。
总的来说,这个人项目完成的很酸爽。。。