- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
编辑:请向下滚动到问题末尾的“编辑”部分,了解最新的详细信息。我不会编辑这篇文章的其余部分来保留评论的历史记录。
我在头文件中定义了一个类:
class TestClass
{
public:
TestClass() { }
~TestClass() { }
void Test();
private:
static const char * const carr[];
static const int iarr[];
};
TestClass::Test()
函数只是确保两个数组都被使用,因此它们不会被优化掉 - 将它们打印到日志中。为了清楚起见,我不会在这里发布。数组在 .cpp 文件中初始化。
上面的例子工作正常,当创建这个类的一个实例时,地址看起来像这样:
t TestClass * 0x20000268
carr const char * const[] 0x8002490 <TestClass::carr>
iarr const int [] 0x800249c <TestClass::iarr>
以0x20...
开头的内存地址属于RAM区,而0x80...
属于ROM/Flash。正如预期的那样,两个数组都被放置在 ROM 中。
但是,如果我将 virtual
限定符添加到类中的任何函数,例如它的析构函数是这样的:
class TestClass
{
public:
TestClass() { }
virtual ~TestClass() { }
void Test();
private:
static const char * const carr[];
static const int iarr[];
};
那么结果是这样的:
t TestClass * 0x20000268
carr const char * const[3] 0x80024b4 <TestClass::carr>
iarr const int [1000] 0x20000270
特别是 - iarr
被放置在 RAM 中,这完全不是我所期望的。
这个文件是这样编译的:
arm-none-eabi-g++ -mcpu=cortex-m7 -mthumb -mfloat-abi=soft -O0 -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -ffreestanding -fno-move-loop-invariants -Wall -Wextra -g3 -DDEBUG -DUSE_FULL_ASSERT -DTRACE -DOS_USE_TRACE_ITM -DSTM32F767xx -DUSE_HAL_DRIVER -DHSE_VALUE=24000000 -I../include -I../system/include -I../system/include/cmsis -I../system/include/stm32f7-hal -std=gnu++11 -fabi-version=0 -fno-exceptions -fno-rtti -fno-use-cxa-atexit -fno-threadsafe-statics -c -o "src\\main.o" "..\\src\\main.cpp"
还有链接部分:
arm-none-eabi-g++ -mcpu=cortex-m7 -mthumb -mfloat-abi=soft -O0 -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -ffreestanding -fno-move-loop-invariants -Wall -Wextra -g3 -T mem.ld -T libs.ld -T sections.ld -nostartfiles -Xlinker --gc-sections -L"../ldscripts" -Wl,-Map,"VirtualClassTestF7.map" --specs=nano.specs -o "VirtualClassTestF7.elf" "@objs.rsp"
这个项目里面有更多的文件,和硬件初始化有关。我不包括那些以保持帖子简短。
是否有任何开关可以控制这种行为?我已经尝试了我能想出的显而易见的部分,这可能与这个问题有一点关系:
-ffunction-sections
和 -fdata-sections
-fno-common
工具链是 arm-none-eabi
。尝试过的版本(arm-none-eabi-gcc --version
的输出):
第一个来自ARM官方网站:https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads .最后两个来自http://www.freddiechopin.info/en/download/category/11-bleeding-edge-toolchain因为 ARM 官方没有发布 64 位版本,而我们的项目发展到打破 32 位版本的规模。
为什么这是一个问题以及为什么我要专门研究编译器开关:可能还有另一种方法可以通过稍微不同的方式将这些值强制写入 ROM。这不是一个选项——我们最近在一个跨越数千个文件的大型项目中遇到了这个问题,在这个项目中,类继承在各个地方都被大量使用。捕获所有可能出现的此类数组(一些是用宏创建的,一些是由外部工具创建的)然后重新组织所有这些代码是不可能的。因此,我正在寻找编译器以这种确切方式运行的原因以及不涉及接触源文件的可能解决方案。
编辑: 这似乎是 gdb 以及它如何检索该变量的地址的某种问题,或者我遗漏了一些东西。我继续在 PC 上创建了相同的示例(Cygwin gcc 7.4.0):
#include <stdio.h>
class TestClass
{
public:
TestClass() { }
virtual ~TestClass() { }
static const char * const carr[];
static const int iarr[];
};
const char * const TestClass::carr[] = {
"test1", "test2", "test3"
};
const int TestClass::iarr[] = {
1,2,3,4,5,6,7,8,9,0
};
int main() {
TestClass instance;
printf("instance: %p, carr: %p, iarr: %p\n", &instance, instance.carr, instance.iarr);
fflush(stdout);
while(1);
return 0;
}
程序的输出是这样的:
instance: 0xffffcba8, carr: 0x100403020, iarr: 0x100403040
map 文件也证实了这一点。相关部分:
.rdata 0x0000000100403000 0xa0 ./src/main.o
0x0000000100403020 TestClass::carr
0x0000000100403040 TestClass::iarr
但是 gdb 显示了这一点:
p instance.iarr
$2 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0}
p &instance.iarr
[New Thread 57872.0x4f28]
$3 = (const int (*)[10]) 0x60003b8a0
p &instance.iarr
$4 = (const int (*)[10]) 0x60003b8d0
更有趣的是,每次我尝试用 gdb 打印时,这个地址都会发生变化。这是什么原因?
问题标题和标签已调整。
最佳答案
gdb 将你的数组复制到 RAM 中,你甚至不需要它的实例,一个带有 vtable 的类就足够了:
(gdb) p TestClass::iarr
$1 = {1, 2, 3, 4, 5, 6}
(gdb) p (int*)TestClass::iarr
$2 = (int *) 0x7ffff7a8b780
(gdb) p *(int *) 0x7ffff7a8b780 @ 100
$3 = {1, 2, 3, 4, 5, 6, 0 <repeats 94 times>}
(gdb) p (int*)TestClass::iarr
$4 = (int *) 0x7ffff7a8b7a0
(gdb) p (int*)TestClass::iarr
$5 = (int *) 0x7ffff7a8b7c0
(gdb) p *(int *) 0x7ffff7a8b780 @ 100
$6 = {1, 2, 3, 4, 5, 6, 0, 0, 1, 2, 3, 4, 5, 6, 0, 0, 1, 2, 3, 4, 5, 6, 0 <repeats 78 times>}
我想这归结为 gdb 对“C”的解释。如果你需要 gdb 中的真实地址,你需要一个返回它的函数。
关于c++ - gdb 为具有虚函数的类打印非字符串值的静态 const 数组的无效地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55183894/
关闭。这个问题是opinion-based .它目前不接受答案。 想要改进这个问题? 更新问题,以便 editing this post 可以用事实和引用来回答它. 关闭 5 年前。 Improve
在 C# 静态方法中是否有一种方法可以引用定义该方法的类型? 在实例方法中,您可以通过以下方式确定类型: public void Foo() { Type type = this.GetTyp
WPF:静态、动态资源以及资源词典 静态资源与动态资源 我们常常会使用样式或者控件模板放在Window.Resources中,比如这样: 静态资源与动态资源使用如下: <Window
任何人都知道如何在共享/静态函数中动态加载控件?该函数本身位于 mustinherit/abstract 类中。 (这是 VB 中的 ASP.NET 项目)我想做这样的事情: VB: Publ
在我看来,静态/强类型编程语言最宝贵的一点是它有助于重构:如果/当您更改任何 API,那么编译器会告诉您该更改破坏了什么。 我可以想象用运行时/弱类型语言编写代码......但我无法想象没有编译器的帮
正如我的名字所暗示的,我是一名 .NET 开发人员,但我对 Java 的兴趣越来越大,并且我有兴趣学习更多其他语言,因为这有助于我学习更多关于编程的知识。 无论如何,我的问题是:不带参数/不使用状态的
我在java中使用WireMock来 stub POST请求。该请求返回一个存储在我本地的 json 正文文件。 stub 看起来像这样: wireMockServer.stubFor(get(url
Python 是否有类构造函数的机制,即每当首次引用类时(而不是创建该对象的实例时)调用的函数?我知道其他一些语言中也存在这种情况,但我还没有在 Python 中遇到过。 基本上,我想初始化该函数中的
Python 是否有类构造函数的机制,即每当首次引用类时(而不是创建该对象的实例时)调用的函数?我知道其他一些语言中也存在这种情况,但我还没有在 Python 中遇到过。 基本上,我想初始化该函数中的
这个问题已经有答案了: What is the difference between dynamic and static polymorphism in Java? (14 个回答) 已关闭 4 年
这个问题已经有答案了: 已关闭10 年前。 Possible Duplicate: Static initializer in Java 我想知道这个静态的东西(抱歉,这是我第一次遇到这个)对一个类有
如果c++应用程序是按以下方式组织的 //file1.cpp static Y sgObj = X::getInitObject(0); //declared in file scope //fil
我有一个抽象类(AvergedDataRecord),我需要进一步抽象(DataRecord),这样我就可以将它扩展到原始类和一个新的具体类(SummedDataRecord),并且我在获取某些方法时
我正在尝试制作一个字符串枚举。这是我到目前为止所得到的, private class TypedEnum : IEnumerable { public IEnumerator GetEnume
我选修了一门名为“安全代码”的类(class),在下一个作业中,我们应该对一些 C 文件和 JavaEE Web 项目进行静态/动态分析。 我检查了“源监视器”并在 C 文件上运行它,但是(除非我不知
我有两个类,一个是登录类,一个是用户类。在 loggedIn 类中,我想显示我在用户登录时所做的共享首选项。 loginPrefs = getSharedPreferences("loginprefe
我在同一个 Activity 中有两个静态 fragment ,在“fragmentA”中我有一个自定义列表,当一个项目被点击时必须在“fragmentB”中出现一个细节,细节只在我改变屏幕方向时出现
在 Java 中是未修改方法变量,缺少final,每次都重新初始化限定符 静态方法 实例方法 如果 1. 或 2.(或两者)的答案是 final 限定符允许 Java 执行优化并存储方法变量只有一次?
我有两个类相互交互。第一个是中心的,如下: public class Datenbank { double winkelPanel = 0; double groessePanel = 0; doub
我有一个 mysql 数据库,它连接基于 Web 的 php 应用程序和 FoxPro 应用程序(是的,foxpro)。在之前的“开发人员”被解雇后开始处理这个问题。 无论如何,我熟悉 AES_Enc
我是一名优秀的程序员,十分优秀!