For similar insructions in English, please see RPI CSCI1200 instructions.
程序内存调试
程序内存错误有很多种,比如内存访问错误(segmentation fault),读取未初始化的数据,数组越界读/写,内存泄漏等等。这些内存错误通常很难通过传统的程序调试器追查出真正原因。内存错误有时不会导致程序立即崩溃。有些有内存错误的程序甚至可能在一些机器上或数据集上正常工作。这些使得追查内存错误更加困难。
Dr. Memory
Dr. Memory可在Linux,Windows,MacOSX,和Android操作系统上使用。如有问题,错误报告和讨论,请使用Dr. Memory用户邮件群:http://groups.google.com/group/drmemory-users
请通过发邮件至Dr. Memory用户组 报告有关使用Dr. Memory的问题。报告中务必写明操作系统和Dr. Memory版本号等详细信息。
Dr. Memory在Linux或Mac OSX
- 从https://github.com/DynamoRIO/drmemory/wiki/Downloads下载对应操作系统的Dr. Memory压缩(tar.gz)文件。
- 保存并解压包到您选择的目录。比如使用命令:
tar -xvzf DrMemory-YourOperatingSystem-VersionXX.tar.gz
从现在起,我们假设DrMemory存在在目录 ~/DrMemory-YourOperatingSystem/。 - Dr. Memory可以用在32位或64位程序上(只在Linux上),但针对32位程序,Dr. Memory能追踪和报告更多类型的内存错误。所以建议你最好能建立和运行32位应用程序。在64位的Ubuntu操作系统上,你可能会想安装这些额外的软件包:
sudo apt-get install g++-multilib - 你可以在你的编译器中使用-m32,从而编译和生成32位程序。请务必使用-g选项生产调试信息。例如:
g++ -g -m32 main.cpp foo_main.cpp foo_other.cpp -o foo.out - 在Dr. Memory中运行你的程序。例如:
~/DrMemory-YourOperatingSystem-VersionXX/bin/drmemory -brief -- foo.out arg1 arg2
使用你的可执行文件和命令行参数替换“foo.out arg1 arg2”。 - Dr. Memory会在运行过程中将错误打印在屏幕上,同时在程序终止时打印所发现错误摘要。
在Windows上安装Dr. Memory
- 获取Dr. Memory。您可以下载和运行安装程序(.msi文件)将Dr. Memory安装在系统路径上。或者,您可以下载.zip文件在本地直接使用而无须安装。https://github.com/DynamoRIO/drmemory/wiki/Downloads
- 在.msi文件双击运行安装程序。
单击下一步;
勾选接受许可证,然后单击下一步:
你可以安装Dr. Memory在默认位置( C:\Program Files (x86)\Dr. Memory\);
单击下一步;
点击安装;
你会被要求确认是否要对机器进行管理更改;
快速安装后,按完成。 - 请按照下面的说明来编译和使用MinGW g++,Visual Studio IDE,或Visual Studio命令提示符运行程序。
Dr. Memory和MinGW
Dr. Memory不支持使用Cygwin模拟层的程序。因此,我们不能将Dr. Memory用在Cygwin内置g++编译的程序。我们需要改用MinGW g++编译器(Minimalist GNU for Windows)编译我们的程序:
- 确保安装MinGW的G ++编译器。详情参见Cygwin的安装说明。
- 打开Cygwin的终端,进入到存放你的源代码文件的目录,然后使用MinGW的编译器编译程序:
i686-pc-mingw32-g++.exe -static-libgcc -static-libstdc++ -ggdb -o foo.exe foo_main.cpp foo_other.cpp - 您可以通过使用以下命令在Dr. Memory下运行程序:
drmemory -brief -batch -- foo.exe arg1 arg2
用你的程序名称和程序的命令行参数替换 “foo.exe arg1 arg2:。
Dr. Memory和Visual Studio
您也可以将Dr. Memory用在微软的Visual Studio编译器编译的程序:
- 用Visual Studio编译你的应用程序成32位程序(32位是默认编译目标)。请务必确认生成调试信息。您可以通过查看编译目标的属性来验证你的程序是否包含调试信息:
按Alt-F7,弹出配置属性;
在“配置属性| C / C ++ |常规”(Configuration Properties | C/C++ | General)中,“调试信息格式”(Debug Information Format)项要么说“程序数据库(/Zi)”或者“编辑程序数据库并继续(/ZI)”;
此外,在“配置属性|链接|调试”(Configuration Properties | Linker | Debugging)中,“生成调试信息”(Generate Debug Info)项应该是“Yes(/DEBUG)”。如果是Visual Studio 2015,在“配置属性|链接|调试”(Configuration Properties | Linker | Debugging)中,“生成调试信息”(Generate Debug Info)项应为“优化调试Optimized for debugging(/ DEBUG)” - 它不应该是“优化连接速度Optimized for faster linking(/ DEBUG:FASTLINK) “。 - 禁用动态检查:Visual Studio编译器的/RTC1选项会干扰Dr. Memory,使其无法发现读取未初始化的读取局部变量的程序错误,而/RTC1自带的检查读取未初始化变量功能不如Dr. Memory的有效。然而,/RTC1会进行堆栈检查,而Dr. Memory没有此功能,所以要取得最好的效果,你的应用程序应该在使用Dr. Memory时禁用/RCT1,而在不使用Dr. Memory时开启/RTC1。
在Visual Studio IDE中,按下Alt + F7,然后在“配置属性| C / C ++ |代码生成(Configuration Properties | C/C++ | Code Generation)”确保“基本运行时检查(Basic Runtime Checks)”设置成“默认(Default)”。 - 较新版本的Dr. Memory安装程序(1.8及更高版本)会安装Dr. Memory成Visual Studio的“外部工具(External Tool)”。它添加了一个新的菜单项,使你可以在IDE中直接运行Dr. Memory。
现在,您可以选择“工具(Tools)|Dr. Memory”菜单项,Visual Studio则将在Dr. Memory中运行您的应用程序。你可以在“$(TARGETPATH)”之后在结尾处添加参数。 - Dr. Memory(连同你程序)的输出将被打印到Visual Studio输出窗口。在程序运行中,Dr. Memory将错误报告打印在屏幕。并在程序终止时打印所发现的错误的摘要。您可以通过双击错误报告中的文件行而自动打开该文件并跳转到指定的行号。
使用Visual Studio编译没有Visual Studio集成开发环境(IDE)
- 启动Visual Studio命令提示符。从开始菜单,在所有程序,找到你的Visual Studio版本(例如,2010),并展开它。然后,展开Visual Studio工具。选择“Visual Studio 2010的命令提示符”。 (请不要使用64位(x64)或交叉工具(Cross Tool)的版本。)
注意:这不是Cygwin的命令窗口。
此命令提示符程序是一个执行了附带的Visual Studio的批处理文件命令的提示符程序的窗口。这个批处理文件称为vcvars.bat,它设置了为运行在命令行编译器所需的路径和环境变量。
注意:您可以从批处理文件中提取环境变量并在你的.bashrc设置它们,这样你就可以从Cygwin中编译程序。 - 在命令行,进入到包含程序源文件的目录。
- 运行编译器,它被称为“cl”。这会在当前目录中编译所有的.cpp文件并生成hw.exe:
cl /Zi /MT /EHsc /Oy- /Ob0 /Fehw.exe *.cpp - 如果你之前是安装的Dr. Memory,你可以直接运行drmemory。例如:
drmemory -brief -- foo.exe arg1 arg2
运行此命令,请用可执行文件名和命令行参数替换 “foo.exe arg1 arg2”。
如果在程序运行中您没有看到任何额外的从Dr. Memory打印的输出,去掉-batch,Dr. Memory的输出将被写入一个文件,记事本程序将自动启动并显示此文件:
drmemory -brief -- foo.exe arg1 arg2 - Dr. Memory将在程序终止时打印关于它发现的程序错误的摘要。