在可执行文件的哪个段(.BSS,.DATA,其他)中存储了静态变量,以便它们没有名称冲突?例如:
foo.c: bar.c:
static int foo = 1; static int foo = 10;
void fooTest() { void barTest() {
static int bar = 2; static int bar = 20;
foo++; foo++;
bar++; bar++;
printf("%d,%d", foo, bar); printf("%d, %d", foo, bar);
} }
Run Code Online (Sandbox Code Playgroud)
如果我编译两个文件并将其链接到重复调用fooTest()和barTest的main,则printf语句将独立增加.有意义,因为foo和bar变量是翻译单元的本地变量.
但是存储分配在哪里?
需要明确的是,假设您有一个工具链可以输出ELF格式的文件.因此,我相信,有有将一些空间,对于那些静态变量的可执行文件保留.
出于讨论目的,我们假设我们使用GCC工具链.
我所知道的是全局和静态变量存储在.data段中,未初始化的数据存在于.bss段中.我不明白的是为什么我们有未初始化变量的专用段?如果未初始化的变量在运行时分配了值,那么该变量是否仅存在于.bss段中?
在以下程序中, a是在.data段中,并且b在.bss段中; 那是对的吗?如果我的理解是错误的,请纠正我.
#include <stdio.h>
#include <stdlib.h>
int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9};
int b[20]; /* Uninitialized, so in the .bss and will not occupy space for 20 * sizeof (int) */
int main ()
{
;
}
Run Code Online (Sandbox Code Playgroud)
另外,请考虑以下程序,
#include <stdio.h>
#include <stdlib.h>
int var[10]; /* Uninitialized so in .bss */
int main ()
{
var[0] = 20 /* …Run Code Online (Sandbox Code Playgroud) 正如标题所说,
一个典型的答案是:
允许任何和所有代码转换不会改变程序的可观察行为的规则
我们会不时地从某些实现中获取行为,这些行为归因于此规则.好多次错了.那么,这个规则究竟是什么呢.标准没有明确地将此规则作为一个部分或段落提及,那么究竟什么属于这条规则的范围?对我来说,这似乎是一个灰色区域,标准没有详细定义.有人可以根据标准的参考资料详细说明细节.
注意:将其标记为C和C++,因为它与两种语言都相关.
在阅读有关汇编程序的文章时,我经常遇到人们在写文件时他们推送处理器的某个寄存器并稍后再次弹出它以恢复它之前的状态.
这个问题旨在填补关于该主题的良好免费信息的真空.
我相信一个好的答案将适合一个大的答案或至少在几个答案.
主要目标是为完整的初学者提供足够的信息,以便他们可以自己学习手册,并能够理解与分页相关的基本操作系统概念.
建议的指导方针:
相关问题以及为什么我认为它们不是愚蠢的:
x86页表如何工作?:标题与此问题几乎相同,但是正文询问与cr3和TLB相关的具体问题.那个问题是这个问题的一个子集.
x86虚拟化如何工作:正文仅询问源.
(gdb) n
134 a = b = c = 0xdeadbeef + ((uint32_t)length) + initval;
(gdb) n
(gdb) p a
$30 = <value optimized out>
(gdb) p b
$31 = <value optimized out>
(gdb) p c
$32 = 3735928563
Run Code Online (Sandbox Code Playgroud)
gdb如何优化我的价值?
内核如何获得在linux下运行的可执行二进制文件?
这似乎是一个简单的问题,但任何人都可以帮助我深入挖掘?如何将文件加载到内存以及如何启动执行代码?
任何人都可以帮助我,一步一步地告诉我们发生了什么吗?
c代码:
// program break mechanism
// TLPI exercise 7-1
#include <stdio.h>
#include <stdlib.h>
void program_break_test() {
printf("%10p\n", sbrk(0));
char *bl = malloc(1024 * 1024);
printf("%x\n", sbrk(0));
free(bl);
printf("%x\n", sbrk(0));
}
int main(int argc, char **argv) {
program_break_test();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译以下代码时:
printf("%10p\n", sbrk(0));
Run Code Online (Sandbox Code Playgroud)
我收到警告提示:
format ‘%p’ expects argument of type ‘void *’, but argument 2 has type ‘int’
问题1:为什么?
在我之后malloc(1024 * 1024),程序突破似乎没有改变.
这是输出:
9b12000
9b12000
9b12000
Run Code Online (Sandbox Code Playgroud)
问题2:进程在启动以备将来使用时是否在堆上分配内存?或者编译器改变分配的时间点?否则,为什么?
[更新]摘要:brk()或mmap()
在查看TLPI并检查手册页(在TLPI的作者的帮助下)之后,现在我了解了如何malloc()决定使用brk()或mmap(),如下所示:
mallopt() …
根据我的理解,堆栈用于存储值类型(如枚举和结构)和引用到堆中的对象(如类实例)的变量。此外,Stack 还以 LIFO 方式保存带有各自参数等的函数调用。
在 C 中,有4 个通用内存段(堆、堆栈、数据、代码),其中数据段通常存储全局变量和静态变量,这意味着它们存储和管理的内存完全独立的方面,但我这样做相信 Java 以不同的方式处理它(在 JVM 方面有一些魔法)。
如果我在 Swift 中声明了一个全局变量,变量将如何/在哪里存储?例如,与在 XCode 的项目模块中声明全局/静态变量/函数相比,如果我只是玩弄 Playground 文件,这会有所不同吗?