问题描述
我们都知道C#调用C++dll有两种方式:静态调用和动态调用。静态调用调用方式简单,被调用的dll会在程序加载时一起加载到内存中,如果在程序文件夹中没有dll文件,程序会报错。而动态调用调用方式复杂,需借助于API函数来完成dll的加载,卸载及方法调用,就算在程序文件夹中没有dll文件,也可以使程序不报错。另外,在很多文档中都提到动态调用方式能更加有效地使用内存。对于这点我不是很能理解,这里所说的“更加有效”是什么意思?是不是因为静态调用中程序加载时dll会一起加载进内存并一直存在于内存中,而动态调用可以人为的去加载dll,调用方法,使用完又卸载dll,这样就不会一直占用内存。另外,静态调用会导致内存泄露吗?或者说dll调用方法跟内存泄露有必然联系吗?
解决方案
解决方案二:
我也不能理解,哪篇文档提到的?
解决方案三:
动态加载,个人感觉和LAZY的效果很相似。
解决方案四:
引用1楼shingoscar的回复:
我也不能理解,哪篇文档提到的?
我也不记得在哪里见过的,但是确实有这种提法。不知道使用动态加载最大的好处是什么?
解决方案五:
你说的静态应该是简单的DllImport,动态是自行LoadLibrary+GetProcAddress+FreeLibrary。首先DllImport不是在程序加载时加载dll的,而是第一次调用DllImport定义的方法时才加载。静态的优点当然就是简单,缺点是不够灵活,比如DllImport只能使用系统默认的方式查找dll,无法在运行时自行查找;.net程序可以使用AnyCPU方式编译,同时支持x86或x64方式,而c/c++不行,DllImport无法根据当前运行环境自动加载不同的dll;用DllImport加载后无法卸载。一般,对于大部分应用来说,简单的DllImport就足够。动态方式大部分是用于制作框架/类库,比如像sqlce/sqlite提供的.net库,实际是对原生c/c++写的dll的封装,如果让用户使用的时候再额外下载和部署原生的dll就很麻烦,所以最好的方式就是把原生dll嵌入.net程序集,这样用户引用就很方便。程序在运行时会从嵌入资源中释放原生dll,可以自行定义位置,比如系统temp路径下,然后LoadLibrary动态加载使用。这样,也可以做到AnyCPU方式的.net程序集在运行时自动判断环境,提供x86或x64方式的支持,用户的程序使用时就不需要限制死运行方式了。也可以使用LoadLibrary+DllImport的方式,只要在使用DllImport的方法前用LoadLibrary加载过同样名字的dll,DllImport就不会再加载了。这里不直接存在什么内存泄露的事情,无论哪种,加载dll一般都是一次性的事,不会一直不停加载。也没有什么有效利用内存的说法,DllImport本身也要通过LoadLibrary+GetProcAddress,在内存方面没什么区别。只不过LoadLibrary方式可以自己拿到handle,如果需要可以FreeLibrary卸载,不过这应该没多少应用场景。