我正在学习一些具有 C++ 背景的 Java 课程和对象课程。我想知道为什么我们不能选择在堆栈内存上声明的对象?为什么除了原始类型之外的所有内容都必须放在堆上?
这是澄清我所问内容的一些内容。
本质上,如果我们有:
Scanner input = new Scanner(System.in);
那么为什么我们不能首先将它放在堆栈上呢?
最近,我一直在从《从头开始编程》一书中学习 x86 汇编,但我有一台 x86-64 计算机,所以事情在某一时刻开始出错(在本书的早期)。我谈到了处理函数的部分,特别是电源示例。在此示例中,他将参数压入堆栈,然后将它们复制到函数后面的寄存器中。他的代码如下:
pushl $3 # second argument
pushl $2 # first argument
call power # call function
...
power:
pushl %ebp # save old base pointer
movl %esp, %ebp # make stack pointer the base pointer
subl $4, %esp # get room for our local storage
movl 8(%ebp), %ebx # put first argument in %eax
movl 12(%ebp), %ecx # put second argument in %ecx
Run Code Online (Sandbox Code Playgroud)
当然,这是32位的,而我运行的是64位,所以我尝试更新寄存器和指令后缀,最终得到这样的结果(这次不需要注释):
pushq $3
pushq $2
call power
...
power: …Run Code Online (Sandbox Code Playgroud) 我是 C++ 新手,尝试了解如何在 C++ 中创建和使用类。为此,我有以下代码:
class MyClass
{
public:
MyClass()
{
_num = 0;
_name = "";
}
MyClass(MyClass* pMyClass)
{
_num = pMyClass->_num;
_name = pMyClass->_name;
}
void PrintValues() { std::cout << _name << ":" << _num << std::endl; }
void SetValues(int number, std::string name)
{
_num = number;
_name = name;
}
private:
int _num;
std::string _name;
};
int main()
{
std::vector<MyClass*> myClassArray;
MyClass myLocalObject = new MyClass();
for (int i = 0; i < 3; i++)
{ …Run Code Online (Sandbox Code Playgroud) 好吧,我的问题如下,我在某处看到一个linux进程在堆栈上分配8 MiB供使用,例如,如果我有一个C程序,我只在堆栈上分配两个变量,这是正确的说法我分配了或者更好地说我只是重复使用了该空间?由于进程在堆栈上分配 8 MiB,因此它不取决于我将在程序中使用的大小,只要它不超过我的堆栈,即无论哪个术语合适,我都会在堆栈或者我将重用Linux进程已经分配的数据?
#include <stdio.h>
void f() {
int x = 5;
printf("Value = %d End = %p\n", x, &x);
}
void g() {
int y = 10;
printf("Value = %d End = %p\n", y, &y);
}
int main(){
f();
g();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
看到地址将是相同的,因为我重复使用了已经分配的大小,而 malloc 不会发生同样的情况,总结术语“在堆栈中分配正确的数据”不是很正确?
进行一些基本的反汇编,并注意到由于某种原因,缓冲区被给予了额外的缓冲区空间,尽管我在教程中看到的内容使用相同的代码,但仅给出了正确的(500)个字符长度。为什么是这样?
我的代码:
#include <stdio.h>
#include <string.h>
int main (int argc, char** argv){
char buffer[500];
strcpy(buffer, argv[1]);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
用GCC编译,反汇编代码为:
0x0000000000001139 <+0>: push %rbp
0x000000000000113a <+1>: mov %rsp,%rbp
0x000000000000113d <+4>: sub $0x210,%rsp
0x0000000000001144 <+11>: mov %edi,-0x204(%rbp)
0x000000000000114a <+17>: mov %rsi,-0x210(%rbp)
0x0000000000001151 <+24>: mov -0x210(%rbp),%rax
0x0000000000001158 <+31>: add $0x8,%rax
0x000000000000115c <+35>: mov (%rax),%rdx
0x000000000000115f <+38>: lea -0x200(%rbp),%rax
0x0000000000001166 <+45>: mov %rdx,%rsi
0x0000000000001169 <+48>: mov %rax,%rdi
0x000000000000116c <+51>: call 0x1030 <strcpy@plt>
0x0000000000001171 <+56>: mov $0x0,%eax
0x0000000000001176 <+61>: leave
0x0000000000001177 <+62>: ret
Run Code Online (Sandbox Code Playgroud)
然而,这个视频 …
我知道在 Dart 中所有数据类型都是对象,包括数字和布尔值,在其他语言中数字和布尔值存储在堆栈中,复杂数据(如对象或列表)存储在堆中,在 Dart 中它如何存储它?内存中的值?我只想知道这一点。
在下面的 C 程序中,对函数的调用创建了一个相当大的局部变量buf,然后函数返回并且程序处于无限循环中。buf正如人们所预料的那样,在调用该函数时,系统的 RAM 使用量会增加等于 的大小;但是,函数返回后(显示“完成”),RAM 使用量不会下降,而是保持不变。
为什么函数返回后这个堆栈分配的缓冲区没有立即释放?如何制定这种行为的一般行为,并描述在哪些情况下它可能会或可能不会立即释放?
#include <stdlib.h>
#include <stdio.h>
void f()
{
int buf[1000 * 1000 * 200];
}
int main()
{
f();
printf("Done\n");
for (;;);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
PS 这是在 Linux Ubuntu 上运行的。
PS 我编译时没有进行编译器优化
PSf以“闪烁”方式调用(重复[开 - 延迟 - 关 - 延迟])而不是一次调用会导致类似的 RAM 使用时间线。
我最近收到了一份数据结构课程的大学作业,要求我用 C++ 创建一个双向链表。
在处理双向链表时,我需要实现各种功能,但特别引起我注意的一种方法是“clear()”。该方法负责清除双向链表内的所有元素:
void clear(Node* head_ptr)
{
Node* previous_ptr = nullptr;
while(head_ptr != nullptr)
{
previous_ptr = head_ptr; // Store previous node.
head_ptr = head_ptr->next;
delete previous_ptr;
}
};
Run Code Online (Sandbox Code Playgroud)
该方法非常简单;它只是迭代所有元素并为每个元素释放内存Node。然后,我在析构函数中调用此方法,如下所示:
~List()
{
clear_list(m_head_ptr);
};
Run Code Online (Sandbox Code Playgroud)
然后我开始思考。如果我的节点元素位于堆上,这种释放内存的方法就很好,如下所示:
int main()
{
List list;
Node* node_1 = new Node(3, nullptr); // The tail node.
Node* node_2 = new Node(1, node_1);
Node* node_3 = new Node(5, node_2);
Node* node_4 = new Node(7, …Run Code Online (Sandbox Code Playgroud) 在下面的示例代码中,我想知道两次调用log_cref_address何时可靠地打印相同的地址.
#include <iostream>
#include <thread>
#include <functional>
using namespace std;
void log_cref_address(const int& t) {
cout << addressof(t) << ' ';
}
template <int i>
void foo() {
log_cref_address(i); // different if foo called from different threads
thread([] { log_cref_address(i); }).join(); // same if already in thread
thread(log_cref_address, i).join(); // same if already in thread
cout << endl;
}
int main() {
// first three calls print identical addresses
cout << "foo<0>: "; foo<0>();
cout << "foo<0>: "; …Run Code Online (Sandbox Code Playgroud) c++ cross-platform addressof stack-memory pass-by-const-reference
我开发了如下的阻塞队列类
class Blocking_queue
{
public:
Blocking_queue();
int put(void* elem, size_t elem_size);
int take(void* event);
unsigned int get_size();
private:
typedef struct element
{
void* elem;
size_t elem_size;
struct element* next;
}element_t;
std::mutex m_lock;
std::condition_variable m_condition;
unsigned int m_size;
element_t* m_head;
element_t* m_tail;
};
Run Code Online (Sandbox Code Playgroud)
我希望该类尽可能通用,因此我正在使用一个void指针,该指针在元素添加到队列时分配,在从队列中删除时释放。
int Blocking_queue::take(void* event)
{
element_t* new_head = NULL;
int ret = 0;
// Queue empty
if(nullptr == m_head)
{
// Wait for an element to be added to the queue
std::unique_lock<std::mutex> unique_lock(m_lock);
m_condition.wait(unique_lock);
}
if(nullptr == realloc(event, …Run Code Online (Sandbox Code Playgroud) stack-memory ×10
heap-memory ×5
c++ ×4
assembly ×3
c ×3
x86-64 ×3
linux ×2
addressof ×1
constructor ×1
dart ×1
function ×1
java ×1
list ×1
memory ×1