如何查找C++源代码、DLL或VC++编译器创建的任何文件中的所有全局变量?

问题描述 投票:0回答:8

我正在使我的应用程序线程安全。步骤之一是同步访问或消除全局变量的使用。我正在使用 Visual Studio。我找不到任何好方法来查找代码库中的所有全局变量。创建一个好的文本搜索模式是不可能的,而且我找不到任何有用的工具。大家知道有什么好的办法吗?它可以是源代码分析工具或二进制文件分析器。

c++ multithreading visual-studio visual-c++ thread-safety
8个回答
15
投票

这可能有帮助:

  1. 在 Visual Studio 中打开项目。
  2. 打开项目的“类视图”
  3. 在项目标题下,您将找到“全局函数和变量”。

我已使用 Visual Studio 2010 及更高版本检查过这一点。

编辑:按照评论中Ajay的建议,您还可以对项目进行分组。对于项目分组:

  1. 在类视图中,右键单击项目标题
  2. 选择“按对象/成员类型分组”
  3. 选择所需的树,如变量、结构或枚举等。

8
投票

一种选择可能是让链接器生成映射文件(Visual Studio 中的 /MAP)。

您将获得每个二进制文件的 .map 文件,其中包含两个部分:

段表

 Start         Length     Name                   Class
 0001:00000000 00010000H .textbss                DATA
 0002:00000000 000034b4H .text                   CODE
 0003:00000000 00000104H .CRT$XCA                DATA
 0003:00000104 00000104H .CRT$XCAA               DATA
 0003:00000208 00000104H .CRT$XCZ                DATA
 0003:0000030c 00000104H .CRT$XIA                DATA
 ...

符号列表(函数和数据)

  Address         Publics by Value              Rva+Base       Lib:Object

 0000:00000000       ___safe_se_handler_count   00000000     <absolute>
 0000:00000000       ___safe_se_handler_table   00000000     <absolute>
 0000:00000000       ___ImageBase               00400000     <linker-defined>
 0001:00000000       __enc$textbss$begin        00401000     <linker-defined>
 0001:00010000       __enc$textbss$end          00411000     <linker-defined>
 0002:000003a0       _wmain                     004113a0 f   console4.obj
 ...

您可以通过段列表中的“代码”/“数据”名称来区分函数和变量。

优点:您将获得所有未被链接器删除的符号,甚至是库中的符号。

缺点:您将获得链接器未删除的所有符号,甚至是库中的符号。我不知道有什么工具可以自动进行代码/数据分离。


3
投票

我知道http://code.google.com/p/data-race-test/wiki/ThreadSanitizer程序(谷歌的产品)可以在Windows和编译代码上运行。它是动态检测程序(如 valgrind 或有点像 qemu/virtualbox),它为内存访问添加了一些检查。它将尝试发现一些线程问题。您可以在threadsanitizer的控制下运行您的程序。动态转换和检测代码将会导致速度减慢(速度减慢 20 倍至 50 倍)。但有些问题会自动检测到。

它还允许您在源代码中注释一些自定义同步函数。

程序的 Wiki 有指向其他线程竞争检测器的链接:http://code.google.com/p/data-race-test/wiki/RaceDetectionLinks


2
投票

cppclean是一个可以帮助你的静态分析工具。来自文档:

cppclean finds global/static data that are potential problems when using threads.

下面是一个带有静态局部变量和全局变量的简单示例。

./example.h:

void foo();

./example.cpp:

#include "example.h"

int globalVar = 42;

void foo(){
    static int localStatic = 0;
    localStatic++;
}

打开终端并运行 cppclean,如下所示:

$ cppclean --include-path . example.cpp
example.cpp:3: static data 'globalVar'
example.cpp:6: static data 'localStatic'

不幸的是,cppclean 有一些解析问题bug。然而,这些问题非常罕见,并且影响的比例低于我测试过的所有代码。


2
投票

您可以尝试使用CppDepend,使用其代码查询语言

from  f in Fields where f.IsGlobal select f


1
投票

也许

dumpbin
工具会有所帮助。您可以使用
/SYMBOLS
键运行它以显示 COFF 符号表并查找外部符号 - 全局变量应该在此列表中。 转储/符号


0
投票

你们都把事情搞得太复杂了。

1. 将每个文件的代码(一次一个与其他文件分开)复制到字符串或宽字符串等,然后解析出从“{”到“}”不包含的所有内容。将结果保存到外部文件。第一次之后,然后追加到该文件。

2. 即使在所有解析之后剩下的内容总共有 1,000 行,其中也包含了所有全局变量(取决于您如何创建全局变量)。如果您通过名称空间等创建它们,则返回并解析它们。我怀疑大多数程序员是否会拥有 1,000 个全局变量,但对于某些应用程序来说,这可能就是他们所使用的。如果此时您没有太多结果,请手动编辑结果的文本文件。

我发现这个网站上 90% 以上的答案可能都过于复杂,只会占用 CPU 时间和内存空间。保持简单。

您可能会发现有一个 globals.h 文件很方便,您可以尽早加载该文件并将大部分或全部全局变量保留在那里。看来是时候进行大量清理工作了。


0
投票

clang-query
中,所有全局变量都可以使用

列出
match varDecl(hasGlobalStorage())

举个更复杂的例子,找到所有指向

my_type
,

的指针的全局变量
match varDecl(hasGlobalStorage(), hasType(pointerType(pointee(hasUnqualifiedDesugaredType(recordType(hasDeclaration(cxxRecordDecl(hasName("my_type")))))))))

这找到了所有

  • 传统的全局变量
  • static
    函数内的变量
  • static
    类的成员变量

请参阅仅在输入文件上运行 clang-query 了解如何限制结果。

请注意,如果全局变量出现在从未实例化的模板中,上面将列出它,即使编译的代码中实际上不存在这样的全局变量。

© www.soinside.com 2019 - 2024. All rights reserved.