VS C++工程类成员初始化检测脚本
最近项目中出现由类成员未初始化而进行读写而造成的问题,于是想将项目中所有的为初始化的地方找出来,优化一下代码,维护了这么多年的程序已有百万余行且VS2015还尚未支持检查类成员初始化的方法。,于是想写一个小工具帮助我们检查这些纰漏,于是向老大请示后开写,之前没有用过什么脚本写过工具,听说python挺火,于是我要上岸。
现学现用写了2天,写出来一个完全op的搓诞的玩意儿,太丑了,因为不能花太多时间在上面还有其他任务。不过能用来分析一个工程中所有的cpp与h文件效果还不错。
以下是代码,以此为戒
#hfilepath="D:\\Work\\ABSF\\ImportExport\\Import\\Import.vcxproj"
hfilepath="D:\\Work\\ABSF\\Model\\Model.vcxproj"
#hfilepath="D:\\Work\\ABSF\\Persistence\\Persistence.vcxproj"
#hfilepath="D:\\Work\\ABSF\\Language\\LDLPlusSyntaxParser\\LDLPlusSyntaxParser.vcxproj"
#hfilepath="D:\\Work\\ABSF\\Language\\LDLSyntaxParse\\LDLSyntaxParse.vcxproj"
class EMP:
def __init__(self):
self.name = "";
self.decl_defi={}
self.var_ini={}
name_EMP={}
global st
st= []
global insPtr
insPtr=0
privatestr="private:"
publicstr="public:"
protectedstr="protected:"
typedefstr="typedef"
templatestr="template"
friendstr="friend"
commentsstr="//"
DONTWANT=[]
DONTWANT.append(privatestr)
DONTWANT.append(publicstr)
DONTWANT.append(protectedstr)
DONTWANT.append(typedefstr)
DONTWANT.append(templatestr)
DONTWANT.append(friendstr)
DONTWANT.append("CLONE_METHOD")
#DONTWANT.append(commentsstr)
OTHEREXP=[]
OTHEREXP.append('if(')
OTHEREXP.append('while(')
OTHEREXP.append('switch(')
OTHEREXP.append('for(')
Require_Remove=[]
Require_Remove.append('virtual')
Require_Remove.append('friend')
Require_Remove.append('mutable')
Require_Remove.append('MODEL_API ')
Require_Remove.append('ATL_NO_VTABLE ')
Require_Remove.append('PERSISTENCE_API ')
defistr="#define"
classstr= "class "
sturctstr="struct "
enumstr="enum "
equalstr="="
colonstr=":"
semistr=";"
forbracestr="{"
bacbracestr="}"
forparenthstr="("
bacparenthstr=")"
bacbracestrAndSemistr=bacbracestr+semistr
AllFiles=[]
tmppos=-1
def getStack():
global st
global insPtr
if(insPtr!=0):
return st[insPtr-1]
else:
return ""
def pushStack(ele):
global st
global insPtr
st.insert(insPtr, ele)
insPtr+=1
def popStack():
global st
global insPtr
if (insPtr!=0):
insPtr-=1
st.pop(insPtr)
return insPtr
def clearStack():
global st
global insPtr
while popStack()!=0:
pass
def printTab():
global insPtr
for i in range(0,insPtr):
print("\t",end='')
print("\nBegin parse target project files...")
f0=open(hfilepath,'r')
for line in f0:
hpos=line.find('.h')
cpppos=line.find('.cpp')
if hpos>=0 or cpppos>=0:
hpos=line.find('=\"')
if hpos>=0:
cpppos=line.find('"',hpos+2,len(line))
if cpppos>=0:
line=line[hpos+2:cpppos]
#print(line)
NDDBS=0
startpos=0
while True:
if line.find('..\\',startpos,len(line))>=0:
NDDBS+=1
startpos+=len('..\\')
else:
break
if hfilepath.rfind("\\")==-1:
hfilepath+="\\"
tmppos=hfilepath.rfind("\\")
while NDDBS>0:
if hfilepath.rfind("\\",0,tmppos)==-1 or NDDBS==0:
break
else:
tmppos=hfilepath.rfind("\\",0,tmppos)
NDDBS-=1
if NDDBS==0:
#print(hfilepath[0:tmppos+1]+line[startpos:len(line)])
AllFiles.append(hfilepath[0:tmppos+1]+line[startpos:len(line)])
else:
print("!!!!!!!!\\not match")
print("\nBegin analyse all h files...")
for file in AllFiles:
#print(file)
if file.find('.h')>=0:
print("Analysing : "+file+" .....")
#hfilepath="D:\\Work\\ABSF\\Model\\"
#file=hfilepath
#file+="Element"
#file+="XMLImporter"
#file+="Object"
#file+="Model"
#file+="Insertable"
#file+="Configuration"
defineblock=0
codeblock=""
functionname=""
adhesionflag=0
tempstr=""
templongstr=""
#f1=open(file+'.h','r')
f1=open(file,'r')
for line in f1:
if line.find(commentsstr)>0:
line=line[0:line.find(commentsstr)]
for i in range(0,len(DONTWANT)):
if line.find(DONTWANT[i])>0:
i=-1
break
if i!=-1:#舍弃注释..public...选项
for i in range(0,len(Require_Remove)):
if line.find(Require_Remove[i])>=0:
#print(Require_Remove[i])
line=(line[0:line.find(Require_Remove[i])]+line[line.find(Require_Remove[i])+len(Require_Remove[i]):len(line)])
#print(line)
#print(adhesionflag,end='')
#print(" ",end='')
#print(line,end='')
classpos=-1
if line.find(sturctstr)>=0:
classpos=line.find(sturctstr)
if line.find(enumstr)>=0:
classpos=line.find(enumstr)
if line.find(classstr)>=0:
classpos=line.find(classstr)
if classpos>0:
for i in range(classpos-1,-1,-1):#排除 函数(struct情况)
if line[i].isalpha():
break
else:
i=0
#print(classpos)
#结构体枚举类
if line.find(defistr)>=0:#define忽略
if line.find('\\')>0:
defineblock=1
continue
if defineblock==1:
if line.find('\\')==-1:
defineblock=0
continue
if classpos>=0 and i==0:
if (commentsstr in line)==0 or((commentsstr in line)and line.find(commentsstr)>classpos):#是一个class申明或定义
tmppos=line.find(' ',classpos)
if tmppos>0:
tmppos+=1
for i in range(tmppos,len(line)):
if not(line[i]==' 'or line[i]=='\t'):
tmppos=i
break
for i in range(tmppos,len(line)):
if not (line[i].isalpha()or line[i].isdigit()or line[i]=='_') :
#print(line[i],end = '\n')
break
print("")
printTab()
if(len(line[tmppos:i])!=0):
print(line[tmppos:i]+' begin', end = '\n')
else:
print("enum")
pushStack(line[tmppos:i])
if semistr in line:#只是类申明不管
tempstr=getStack()
popStack()
printTab()
print(tempstr+' declaration end'+'\n', end = '\n')
elif (len(line[tmppos:i])!=0):
obj= EMP()#新建类对象
obj.name=line[tmppos:i]
if not(obj.name in name_EMP):
name_EMP[line[tmppos:i]]=obj
elif insPtr>0:
if adhesionflag==0:#代码块起始
codeblock=""
codeblock+=line
adhesionflag=1#标志此代码块成立
blocktype=0#代码块类型0无,1函数,2变量
bracecounter=0#代表没有括号出现
tmppos=line.find(forparenthstr)
#print(tmppos,end=' ')
if tmppos>0 and line.find('declspec')==-1:#有小括号但必须不包含__declspec有分号无大括号是函数调用或者if,swtich,while,for
blocktype=1
if line.find('()(')==tmppos:
tmppos+=2
for i in range(tmppos-1,-1,-1):
if not (line[i]==' 'or line[i]=='\t'):
break
tmppos-=1
for i in range(tmppos-1,-1,-1):
if not (line[i].isalpha()or line[i].isdigit()or line[i]=='~'or line[i]=='_'or line[i]=='&'or line[i]=='['or line[i]==']'or line[i]=='+'or line[i]=='-'or line[i]=='*'or line[i]=='='or line[i]=='<'or line[i]=='!'or line[i]=='('or line[i]==')'):
break
functionname=line[i+1:tmppos]
#print(functionname,end=' ')
#print(line.find(forbracestr))
if line.find(forbracestr)>0:
bracecounter=1
if line.find(bacbracestr)>0:#在一句话中有大括号一对,直接结束代码块,函数定义
bracecounter=0
adhesionflag=-2
else:
tmppos=line.rfind(bacparenthstr)
if line.rfind(semistr)>tmppos:#没有大括号但有在')'之后的分号,函数申明
adhesionflag=-1
if adhesionflag<0:#代码块结束
for i in range(0,len(OTHEREXP)):
if functionname.lower().find(OTHEREXP[i])>0:
i=-1
break
if i==-1:#非函数,为if while for switch
pass#不错浪费时间而已不做处理
else:#
tempstr=getStack()
tmppos=codeblock.find(functionname)
if functionname==tempstr:
if tmppos>=0:
parenthcounter=0
for i in range(tmppos,len(codeblock)):
if codeblock[i]==forparenthstr :
parenthcounter+=1
if codeblock[i]==bacparenthstr :
parenthcounter-=1
if parenthcounter==0:
printTab()
print(codeblock[tmppos:i+1])#构造函数申明部分
templongstr=codeblock[tmppos:i+1]
if adhesionflag==-1 and not (templongstr in name_EMP[tempstr].decl_defi):
name_EMP[tempstr].decl_defi[templongstr]="" #存入构造申明
printTab()
print("decla_stored",end="\n")
if adhesionflag==-2:
name_EMP[tempstr].decl_defi[templongstr]=codeblock#存入构造定义
printTab()
print("defi_stored",end="\n")
#print(len(name_EMP[tempstr].decl_defi[templongstr]))
#print(name_EMP[tempstr].decl_defi[templongstr])
break
adhesionflag=0
#### printTab()
####print("Func: ",end='')
####print(functionname,end='\n')
else:#非函数
blocktype=2
adhesionflag=0
tmppos=line.find(bacbracestr)#}
if tmppos>=0:
if tmppos<line.find(semistr):#}....;为类,结构体,枚举
tempstr=getStack()
popStack()
printTab()
print(tempstr+' end'+'\n', end = '')
if tempstr in name_EMP:#如果该类存在
if len(name_EMP[tempstr].decl_defi)==0:#构造个数
name_EMP[tempstr].decl_defi[tempstr+'()']=""#存入此构造tempstr+'()'+'\n'+'{}'
printTab()
print("construction Func num: ",end="")
print(len(name_EMP[tempstr].decl_defi))
continue
tmppos=line.find(semistr)#只找到';'
if tmppos>0:
if line.find("declspec")==-1:
if line.rfind(equalstr, 0, tmppos)>=0:
tmppos=line.rfind(equalstr, 0, tmppos)
for i in range(tmppos-1,-1,-1):
if not (line[i]==' 'or line[i].isdigit()or line[i]=='\t'or line[i]=='['or line[i]==']'or line[i]=='&'):
break
tmppos-=1
for i in range(tmppos-1,-1,-1):
if not (line[i].isalpha()or line[i].isdigit()or line[i]=='_'):
break
for x in range(i+1,len(line)):
if not (line[x].isalpha()or line[x].isdigit()or line[x]=='_'):
break
tempstr=getStack()
printTab()
print("Member: ",end='')
memname=line[i+1:x]
print(memname,end='')
if line.rfind(equalstr, x, len(line))>=0:
print(" .....Initialized",end='')#已初始化的变量
name_EMP[tempstr].var_ini[memname]=3
else:
name_EMP[tempstr].var_ini[memname]=0
print('')
else:#代码块增量
codeblock+=line
if blocktype==1:#函数相关
if bracecounter==0:#若没有出现过大括号便已有分号结尾
tmppos=line.rfind(bacparenthstr)
if line.rfind(semistr)>tmppos:#没有大括号但有在')'之后的分号,仅为函数申明
adhesionflag=-1
if adhesionflag==1:
if line.find(forbracestr)>0:
bracecounter+=1
if line.find(bacbracestr)>0:
bracecounter-=1
if bracecounter==0:#括号平衡,为函数定义
adhesionflag=-2
if adhesionflag<0:#代码块结束
for i in range(0,len(OTHEREXP)):
if functionname.lower().find(OTHEREXP[i])>0:
i=-1
break
if i==-1:#非函数,为if while for switch
pass#不错浪费时间而已不做处理
else:#
tempstr=getStack()#类名
tmppos=codeblock.find(functionname)
if functionname==tempstr:#构造
if tmppos>=0:
parenthcounter=0
for i in range(tmppos,len(codeblock)):
if codeblock[i]==forparenthstr:
parenthcounter+=1
if codeblock[i]==bacparenthstr:
parenthcounter-=1
if parenthcounter==0:
printTab()
print(codeblock[tmppos:i+1])#构造函数申明部分
templongstr=codeblock[tmppos:i+1]
if adhesionflag==-1 and not (templongstr in name_EMP[tempstr].decl_defi):
name_EMP[tempstr].decl_defi[templongstr]="" #存入构造申明
printTab()
print("decla_stored",end="\n")
if adhesionflag==-2:
name_EMP[tempstr].decl_defi[templongstr]=codeblock#存入构造定义
printTab()
print("defistored",end="\n")
#print(len(name_EMP[tempstr].decl_defi[templongstr]))
#print(name_EMP[tempstr].decl_defi[templongstr])
break
adhesionflag=0
#### printTab()
####print("Func: ",end='')
####print(functionname,end='\n')
f1.close
print("\n Begin analyse all cpp files...")
for file in AllFiles:
if file.find('.cpp')>=0:
print("Analysing : "+file+" .....")
#print("f2 begin")
#cppfilepath=""
classname=""
#f2=open(file+'.cpp','r')
f2=open(file,'r')
adhesionflag=0
tmppos=-1
tmppos1=-1
defineblock=0
for line in f2:
if line.find(commentsstr)>0:
line=line[0:line.find(commentsstr)]
for i in range(0,len(DONTWANT)):
if line.find(DONTWANT[i])>0:
i=-1
break
if i!=-1:#舍弃注释..public...选项
if line.find(defistr)>=0:#define忽略
if line.find('\\')>0:
defineblock=1
continue
if defineblock==1:
if line.find('\\')==-1:
defineblock=0
continue
if adhesionflag==1:#如果粘连部分
codeblock+=line
if bacbracestr in line:
adhesionflag=-1
if adhesionflag==0:
for classname in name_EMP:
tmppos1=line.find('(')
if tmppos1>=0:
tempstr=classname+'::'+classname
tmppos=line.rfind(tempstr,0,tmppos1)
if tmppos>=0 and tmppos1-tmppos>0 and tmppos1-tmppos<2+len(tempstr):#该行属于某类的构造开头
if adhesionflag==0:
adhesionflag=1#标志此为构造块
codeblock=""
codeblock+=line
if semistr in line:
if not (bacbracestr in line):
print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!WHAT THE HELL IS THIS?")
print('target class: ')
adhesionflag=-1
break#终止其他查找
else:
print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!Inside other block")
if adhesionflag==-1:#为代码块终止
adhesionflag=0
construct=""
for construct in name_EMP[classname].decl_defi:
if len(name_EMP[classname].decl_defi[construct])==0:
name_EMP[classname].decl_defi[construct]=codeblock
#print(codeblock)
construct="added"
break
if construct!="added":#不能添加
print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!construct FUNCTION FULL!!!!!!!")
#保存代码块到任意的构造中
#for tempstr in name_EMP[classname].decl_defi:
#tempstr=classname+'::'+tempstr
#if len(name_EMP[classname].decl_defi[tempstr])==0:#目标代码尚未定义的话
#tempstr=classname+'::'+tempstr
f2.close
print("\n=============================================================================\n"+hfilepath[hfilepath.rfind("\\")+1:hfilepath.rfind(".")]+" project's initialization status:\n")
for classname in name_EMP:
if len(name_EMP[classname].var_ini)!=0:#必须有成员
print(classname)
for var in name_EMP[classname].var_ini:
print("\t"+var+';'+" .....",end="")
if name_EMP[classname].var_ini[var]==0:
successed=3#假定是完全
for construct in name_EMP[classname].decl_defi:
tempstr=name_EMP[classname].decl_defi[construct]
for i in range(0,len(tempstr)-1):
if tempstr[i]==colonstr and tempstr[i+1]!=colonstr and tempstr[i-1]!=colonstr:
break;
if i!=len(tempstr)-2:#my lord , we found them
tmppos=tempstr.find(forbracestr,i,len(tempstr))
if tmppos>=0:
if tempstr.find(var,i,tmppos)>=0:
continue#绕过这次
successed=2#不在初始化列表中,假定在构造中
tmppos=tempstr.find(forbracestr,0,len(tempstr))
if tmppos>=0:
if tempstr.find(var,tmppos,len(tempstr))>=0:
continue
successed=1
break
if name_EMP[classname].var_ini[var]==0:
name_EMP[classname].var_ini[var]=successed
if name_EMP[classname].var_ini[var]==3:
print(".....OK")
elif name_EMP[classname].var_ini[var]==2:
print(".....OK in constructor but need to be initialized in initializer list")
elif name_EMP[classname].var_ini[var]==1:
print(".....Uninitialized!!!!!!!!")
else:
print("var_ini Error!!!!")
print(classname+" end\n")
print("=============================================================================\n\n")