在不了解您的最终目标的情况下,除了对内存访问进行建模(例如,您是否要进行验证、测试用例生成等?),这有点难以回答,因为您有很多选择。但是,如果您依赖其中一个 API,您可能最灵活地控制性能问题。例如,您可以如下定义自己的内存访问(z3py 脚本的链接:http ://rise4fun.com/Z3Py/gO6i ):
address_bits = 7
data_bits = 8
s = Solver()
# mem is a list of length program step, of a list of length 2^address_bits of bitvectors of size 2^data_bits
mem =[]
# modify a single address addr to value at program step step
def modifyAddr(addr, value, step):
mem.append([]) # add new step
for i in range(0,2**address_bits):
mem[step+1].append( BitVec('m' + str(step + 1) + '_' + str(i), data_bits) )
if i != addr:
s.add(mem[step+1][i] == mem[step][i])
else:
s.add(mem[step+1][i] == value)
# set all memory addresses to a specified value at program step step
def memSet(value, step):
mem.append([])
for i in range(0,2**address_bits):
mem[step+1].append( BitVec('m' + str(step + 1) + '_' + str(i), data_bits) )
s.add(mem[step+1][i] == value)
modaddr = 23 # example address
step = -1
# initialize all addresses to 0
memSet(0, step)
step += 1
print s.check()
for i in range(0,step+1): print s.model()[mem[i][modaddr]] # print all step values for modaddr
modifyAddr(modaddr,3,step)
step += 1
print s.check()
for i in range(0,step+1): print s.model()[mem[i][modaddr]]
modifyAddr(modaddr,4,step)
step += 1
print s.check()
for i in range(0,step+1): print s.model()[mem[i][modaddr]]
modifyAddr(modaddr,2**6,step)
step += 1
print s.check()
for i in range(0,step+1): print s.model()[mem[i][modaddr]]
memSet(1,step)
step += 1
print s.check()
for i in range(0,step+1): print s.model()[mem[i][modaddr]]
for a in range(0,2**address_bits): # set all address values to their address number
modifyAddr(a,a,step)
step += 1
print s.check()
print "values for modaddr at all steps"
for i in range(0,step+1): print s.model()[mem[i][modaddr]] # print all values at each step for modaddr
print "values at final step"
for i in range(0,2**address_bits): print s.model()[mem[step][i]] # print all memory addresses at final step
这种简单的实现允许您(a)将所有内存地址设置为某个值(如您的 memset),或(b)修改单个内存地址,将所有其他地址限制为具有相同的值。对我来说,运行和编码 128 个地址的大约 128 个步骤需要几秒钟,因此它有大约 20000 个 8 位的位向量表达式。
现在,根据您在做什么(例如,您是否允许像这个 memset 一样对多个地址进行原子写入,或者您是否希望将它们全部建模为单独的写入?),您可以添加更多功能,例如将地址子集修改为程序步骤中的一些值。这将使您能够灵活地权衡建模精度与性能(例如,原子写入内存块与一次修改单个地址,这将遇到性能问题)。此外,此实现不需要 API,您也可以将其编码为 SMT-LIB 文件,但如果使用API 之一。