我可以在编译或链接时从gcc获取单例的地址吗?

时间:2016-03-09 21:40:05

标签: c++ gcc embedded

我正在开发一个嵌入式项目并问我,是否可以在编译或链接时获取单例类的地址。

要创建我的单例,我使用以下代码,并对实例的地址感兴趣。

class A
{
    public:
    static A& get()
    {
        static A instance;
        return instance;
}:

我想要做的,当然是使用调试探针从外部更改值,但不使用真正的调试会话。

祝你好运 安德烈亚斯

4 个答案:

答案 0 :(得分:1)

如果您没有充分了解您正在使用的开发工具,硬件架构等,那么很难确切地说出您应该做什么,但通常可以将某些变量分配给特定数据段或特定代码段中的函数,然后在链接阶段为该段分配特定地址。

例如,您可以使用gcc section attribute

int init_data __attribute__ ((section ("INITDATA")));

MyObj obj __attribute__((section ("BATTERY_BACKED")));

然后在linker script中使用相同的部分名称,将其放置在"右边"地址。

大多数(合理的)嵌入式工具链会以某种方式支持这一点,但具体如何完成它会有很大差异。

另一种选择是使用展示位置new

MyObj *obj = new ((void *)0x11220000) MyObj(args);

答案 1 :(得分:0)

您可以将placement-new与缓冲区一起使用,该缓冲区的地址在编译或链接时可用。

#include <new>

extern unsigned char placeA[];

class A {
public:
    static A& get()
    {
        static A *p_instance;
        if(!p_instance) {
            p_instance = new(placeA) A();
        }
        return *p_instance;
    }
};

unsigned char placeA[sizeof(A)] __attribute__ ((aligned (__BIGGEST_ALIGNMENT__)));

答案 2 :(得分:0)

通常调试探针仅查看物理地址,而用户应用程序仅在虚拟地址上运行,这会更改应用程序加载的所有时间,因此没有链接器技巧可行。你没有说你使用的操作系统,但我猜它是Linux。如果是这样,您可以执行以下操作:保留一个暂存存储区域,您知道操作系统未使用的物理地址。例如,如果您的SoC具有嵌入式静态内存,请使用它,如果不是只询问本地Linux专家如何将RAM页面保留到内核内存配置中。

然后查看本文以了解如何将物理地址映射到应用程序的虚拟内存空间:

how to access kernel space from user space(in linux)?

获取暂存区域的虚拟地址后,您的应用程序可以在任何地方读取/写入。调试探针将能够使用物理地址读/写到同一区域。

答案 3 :(得分:-1)

不确定这是否是您正在尝试做的事情,但在gcc中使用“-S”将在编译阶段后停止所有内容。这样您就可以深入了解汇编代码并评估变量。这是手册摘录:

If you only want some of the stages of compilation, you can use -x (or
filename suffixes) to tell gcc where to start,
and one of the options -c, -S, or -E to say where gcc is to stop.  Note that
some combinations (for example, -x cpp-output -E) instruct gcc to do nothing at all.

-c  Compile or assemble the source files, but do not link.  The linking stage simply is not done.  The ultimate
    output is in the form of an object file for each source file.

    By default, the object file name for a source file is made by replacing the suffix .c, .i, .s, etc., with .o.

    Unrecognized input files, not requiring compilation or assembly, are ignored.

-S  Stop after the stage of compilation proper; do not assemble.  The output is in the form of an assembler code file
    for each non-assembler input file specified.

    By default, the assembler file name for a source file is made by replacing the suffix .c, .i, etc., with .s.

    Input files that don't require compilation are ignored.

-E  Stop after the preprocessing stage; do not run the compiler proper.  The output is in the form of preprocessed
    source code, which is sent to the standard output.

    Input files which don't require preprocessing are ignored.