这一章在现实世界中OCaml中描述了不同数据类型的运行时内存布局。但是,没有关于惰性值的讨论。
lazy_t实现,即它的运行时表示形式是什么以及编译器内置的主要操作是什么?链接到源代码将不胜感激。我查看了CamlinternalLazy模块,但是仅基于对Obj模块中函数的调用,似乎很难解读实际的表示形式。注意:此问题与 OCaml编译器/运行时有关。据我所知,有如何偷懒值应该由没有实施标准规范的 ocaml的编译器/运行。
我最近在接受采访时询问了有关虚拟功能和多重继承的对象布局.
我在没有涉及多重继承的情况下如何实现它的上下文中解释了它(即编译器如何生成虚拟表,在每个对象中插入指向虚拟表的秘密指针等等).
在我看来,我的解释中缺少一些东西.
所以这里有问题(见下面的例子)
示例代码:
class A {
public:
virtual int funA();
private:
int a;
};
class B {
public:
virtual int funB();
private:
int b;
};
class C : public A, public B {
private:
int c;
};
Run Code Online (Sandbox Code Playgroud)
谢谢!
c++ multiple-inheritance virtual-inheritance vtable memory-layout
我正在研究给定进程的内存布局.我注意到每个进程的起始内存位置不是0.在这个网站上,TEXT从0x08048000开始.一个原因可以是使用NULL指针区分地址.我只是想知道是否还有其他好的理由?谢谢.
当然,答案是"不",因为写它的人认为它很难,但我想知道为什么.
考虑到(无模板)类通常在头文件中声明,然后将其包含在几个单独编译的文件中,请考虑这两个文件:
#include <cstddef>
struct Foo {
public:
int pub;
private:
int priv;
};
size_t getsize1(Foo const &foo) {
return sizeof(foo);
}
Run Code Online (Sandbox Code Playgroud)
#include <cstddef>
struct Foo {
public:
int pub;
private:
int priv;
};
size_t getsize2(Foo const &foo) {
return sizeof(foo);
}
Run Code Online (Sandbox Code Playgroud)
通常,Foo将在头文件中声明并包含在两者中,但效果如上所示.(也就是说,包含一个标题不是魔术,它只是将标题内容放在该行上.)我们可以编译它们并将它们链接到以下内容:
#include <iostream>
struct Foo {
public:
int pub;
private:
int priv;
};
size_t getsize1(Foo const &);
size_t getsize2(Foo const &);
int main() {
Foo foo;
std::cout << getsize1(foo) << ", " << getsize2(foo) << …Run Code Online (Sandbox Code Playgroud) 对于某些编译器,如果一个类具有虚函数,则可以使用其对象的第一个字节的地址来访问其 vptr。例如,
\n\nclass Base{\npublic:\n virtual void f(){cout<<"f()"<<endl;};\n virtual void g(){cout<<"g()"<<endl;};\n virtual void h(){cout<<"h()"<<endl;};\n};\n\nint main()\n{ \n Base b;\n\n cout<<"Address of vtbl\xef\xbc\x9a"<<(int *)(&b)<<endl;\n\n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\n\n我知道它取决于不同的编译器行为。既然存在 vptr 被存储为第一个条目的情况,那么这样做有什么好处呢?这是否有助于提高性能,或者仅仅是因为使用 &b 更容易访问 vbtl?
\nI'm playing around with [[no_unique_address]] in c++20.
In the example on cppreference we have an empty type Empty and type Z
struct Empty {}; // empty class
struct Z {
char c;
[[no_unique_address]] Empty e1, e2;
};
Run Code Online (Sandbox Code Playgroud)
Apparently, the size of Z has to be at least 2 because types of e1 and e2 are the same.
However, I really want to have Z with size 1. This got me thinking, what about wrapping Empty in some wrapper …
我想知道一种可能的方法,使类的内存布局在模板化代码中更有效.据我所知,标准要求一个类的数据成员按照其声明的顺序在内存中进行布局.编译器可能会执行填充以使数据成员对齐,从而不必要地增加类的大小.我们的想法是在编译时重新安排数据成员声明,以尽量减少这种填充.我做了一些搜索,但找不到任何信息(大多数时候人们讨论打包编译器指令,这与我看到的不完全相同).
首先,请考虑以下(琐碎,但重复和丑陋)代码(ideone.com上的相同代码)(问题在代码下面,可以随意跳到它们):
#include <iostream>
#include <cstdint>
namespace so
{
template <typename Ta, typename Tb, typename Tc, std::size_t =
((sizeof(Ta) >= sizeof(Tb)) && (sizeof(Tb) >= sizeof(Tc))) ? 10 :
((sizeof(Ta) >= sizeof(Tc)) && (sizeof(Tc) >= sizeof(Tb))) ? 11 :
((sizeof(Tb) >= sizeof(Ta)) && (sizeof(Ta) >= sizeof(Tc))) ? 20 :
((sizeof(Tb) >= sizeof(Tc)) && (sizeof(Tc) >= sizeof(Ta))) ? 21 :
((sizeof(Tc) >= sizeof(Ta)) && (sizeof(Ta) >= sizeof(Tb))) ? 30 :
((sizeof(Tc) >= sizeof(Tb)) && (sizeof(Tb) >= sizeof(Ta))) ? 31 : …Run Code Online (Sandbox Code Playgroud) 是的,已经存在相当多的类似问题(5037601,19166698,4855162,14505995,5052648,13409508,7745146,7459630;对不起,没有足够的代表超过2个链接),是的,有一些很好的文章解释这种东西(点击,点击,http://codearcana.com/posts/2013/05/02/introduction-to-format-string-exploits.html).我已经阅读了它们,我认为我得到了一般的想法,但我仍然失败,成功地利用了我能想到的最简单的训练玩具示例.
#include <stdio.h>
void f(char* a)
{
printf("a: %p\n", &a);
printf(a);
return;
}
void main(int argc, char** argv)
{
f(argv[1]); //please ignore the lack of any check
return;
}
Run Code Online (Sandbox Code Playgroud)
是的,堆栈是可执行的,是的,内存布局随机化被禁用.每次执行都给我相同的地址a.我可以提供它,例如$ ruby -e 'print "AAAA"+("%08x."*16)',这导致:
a: 0xbfffece0
AAAAbfffece0.bfffecf0.b7fd7ff4.00000000.00000000.bffffcf8.080484b0.bfffecf0.00000fff.b7fd8420.00000000.41414141.78383025.3830252e.30252e78.252e7838.
Run Code Online (Sandbox Code Playgroud)
所以现在我可以看到我的输入最终在内存中.我可以用栈写一个值$ ruby -e 'print "12345%n"+("%08x."*16)',结果如下:
a: 0xbfffece0
12345bfffecf0.b7fd7ff4.00000000.00000000.bffffcf8.080484b0.00000005.00000fff.b7fd8420.00000000.34333231.256e2535.2e783830.78383025.3830252e.30252e78.
Run Code Online (Sandbox Code Playgroud)
显然,我的最终目标可能是这样的<something><NOPs><shellcode>,其中<something>覆盖了返回地址,f以便程序将跳转到NOP底座并执行shellcode.但保存的返回地址的地址现在似乎取决于我的输入,对吧?类似的东西0xbfffece0 - len(input) - 12,假设一个12字节的序幕?也许这个例子毕竟不是最简单的......
我很困惑.有任何想法吗?
我从size命令中得到了意外的输出。
Afaik 初始化存储在data段中的全局和静态变量,未初始化并初始化为 0 存储在bss段中的全局/静态变量。
printf("%d",sizeof(int));给出int大小4。然而,bss和data段没有相应地增加至4。
#include <stdio.h>
int main()
{
return 0;
}
C:\Program Files (x86)\Dev-Cpp\MinGW64\bin>size memory-layout.exe
text data bss dec hex filename
10044 2292 2512 14848 3a00 memory-layout.exe
#include <stdio.h>
int g; //uninitialised global variable so, stored in bss segment
int main()
{
return 0;
}
C:\Program Files (x86)\Dev-Cpp\MinGW64\bin>size memory-layout.exe
text data bss dec hex filename
10044 2292 2528 14864 3a10 memory-layout.exe
Run Code Online (Sandbox Code Playgroud)
为什么bss增加了 …
我有一个关于二维数组的内存布局的问题。当我们定义一个,就像 int 一样a[3][4],分配给这个数组的内存是连续的吗?
或者换句话说,二维数组是否被实现为连续的一维数组?
如果答案是肯定的,访问是否a[0][6]等同于访问a[1][2]?
我编写了以下 C 程序。
#include <stdio.h>
int main(){
int a[3][4] = {{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}};
printf("%d %d\n", a[0][6], a[1][2]);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我发现输出是7 7.
a[0][6]看似非法,但它指出a[1][2],我想知道为什么,这样的操作合法吗?
c arrays memory-layout multidimensional-array language-lawyer