在delphi中如何获取字符串的内存地址

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在delphi中如何获取字符串的内存地址相关的知识,希望对你有一定的参考价值。

虽然这个问题简单,但在回答前要说明一下,
delphi2010后的字符串是宽字符格式,关键字是W开头的,内存布局不同于关键字A开头的!
这只是内存排版问题!

VAR
    ss:string;        //定义字符串变量 
    SSpoint:Pointer; //定义字符串指针变量
begin
ss := '示例字符串';
SSpoint := pchar(ss);    //通过PCHAR函数获取字符串地址
ShowMessage(Format('%p=%s',[Pointer(sspoint),sspoint]));
//如果上面的showmessage不正确(可能版本不兼容),可以改为:
ShowMessage(Format('%p=%s',[Pointer(sspoint),StrPas(sspoint)]));
end;
如果针对这个问题的回答还有疑问,可以继续追问我!
如果在DELPHI方面有其他问题,可以点我的名字找找我以前的回答,或者对你有帮助!
如果我的热心回答帮助到你,记得采纳哦!祝你生活愉快!
补上一些参考资料给你:
http://www.cnblogs.com/Bung/category/299846.html
http://wenku.baidu.com/view/3dd18bec5ef7ba0d4a733b40.html

参考技术A 简单到家啊。无论是长字符串还是短字符串,首字符的地址(@s[1])就是字符串的内存地址。
var
s: string; 长字符串
ss: ShortString; 短字符串
begin
s := 'abcde';
ss := '12345';
ShowMessage(IntToStr(Integer(@s[1])));
ShowMessage(IntToStr(Integer(@ss[1])));
end;本回答被提问者和网友采纳

linux内核 - 如何获取物理地址(内存管理)?

【中文标题】linux内核 - 如何获取物理地址(内存管理)?【英文标题】:linux kernel - how to get physical address (memory management)? 【发布时间】:2017-04-26 16:56:40 【问题描述】:

在 Linux 中,

页面全局目录偏移地址(cr3 + index)可以使用pgd_offset() MACRO计算。

Page Upper Directory 偏移地址可以使用 pud_offset() API 计算。

Page Middle Directory 偏移地址可以使用 pmd_offset() API 计算。

页表条目偏移地址可以使用pte_offset_map() MACRO计算。

那么,如何获取物理地址呢? (yellow line in above picture)

有计算物理地址的函数或宏吗?

edit : x86-64 architecture.

【问题讨论】:

【参考方案1】:

Linux 内核使用通用的四页分页模型,不仅适用于 32 位系统,也适用于 64 位系统。分页单元是MMU(内存管理单元)的一部分,它将线性地址转换为物理地址。

我为你写了一个内核模块来模拟虚拟地址到物理地址的转换过程。我假设你知道分页系统的原理。

static void get_pgtable_macro(void)

    printk("PAGE_OFFSET = 0x%lx\n", PAGE_OFFSET);
    printk("PGDIR_SHIFT = %d\n", PGDIR_SHIFT);
    printk("PUD_SHIFT = %d\n", PUD_SHIFT);
    printk("PMD_SHIFT = %d\n", PMD_SHIFT);
    printk("PAGE_SHIFT = %d\n", PAGE_SHIFT);

    printk("PTRS_PER_PGD = %d\n", PTRS_PER_PGD);
    printk("PTRS_PER_PUD = %d\n", PTRS_PER_PUD);
    printk("PTRS_PER_PMD = %d\n", PTRS_PER_PMD);
    printk("PTRS_PER_PTE = %d\n", PTRS_PER_PTE);

    printk("PAGE_MASK = 0x%lx\n", PAGE_MASK);


static unsigned long vaddr2paddr(unsigned long vaddr)

    pgd_t *pgd;
    pud_t *pud;
    pmd_t *pmd;
    pte_t *pte;
    unsigned long paddr = 0;
        unsigned long page_addr = 0;
    unsigned long page_offset = 0;

    pgd = pgd_offset(current->mm, vaddr);
    printk("pgd_val = 0x%lx\n", pgd_val(*pgd));
    printk("pgd_index = %lu\n", pgd_index(vaddr));
    if (pgd_none(*pgd)) 
        printk("not mapped in pgd\n");
        return -1;
    

    pud = pud_offset(pgd, vaddr);
    printk("pud_val = 0x%lx\n", pud_val(*pud));
    if (pud_none(*pud)) 
        printk("not mapped in pud\n");
        return -1;
    

    pmd = pmd_offset(pud, vaddr);
    printk("pmd_val = 0x%lx\n", pmd_val(*pmd));
    printk("pmd_index = %lu\n", pmd_index(vaddr));
    if (pmd_none(*pmd)) 
        printk("not mapped in pmd\n");
        return -1;
    

    pte = pte_offset_kernel(pmd, vaddr);
    printk("pte_val = 0x%lx\n", pte_val(*pte));
    printk("pte_index = %lu\n", pte_index(vaddr));
    if (pte_none(*pte)) 
        printk("not mapped in pte\n");
        return -1;
    

    /* Page frame physical address mechanism | offset */
    page_addr = pte_val(*pte) & PAGE_MASK;
    page_offset = vaddr & ~PAGE_MASK;
    paddr = page_addr | page_offset;
    printk("page_addr = %lx, page_offset = %lx\n", page_addr, page_offset);
        printk("vaddr = %lx, paddr = %lx\n", vaddr, paddr);

    return paddr;


static int __init v2p_init(void)

    unsigned long vaddr = 0;

    printk("vaddr to paddr module is running..\n");
    get_pgtable_macro();
    printk("\n");

    vaddr = (unsigned long)vmalloc(1000 * sizeof(char));
    if (vaddr == 0) 
        printk("vmalloc failed..\n");
        return 0;
    
    printk("vmalloc_vaddr=0x%lx\n", vaddr);
    vaddr2paddr(vaddr);

    printk("\n\n");
    vaddr = __get_free_page(GFP_KERNEL);
    if (vaddr == 0) 
        printk("__get_free_page failed..\n");
        return 0;
    
    printk("get_page_vaddr=0x%lx\n", vaddr);
    vaddr2paddr(vaddr);

    return 0;


static void __exit v2p_exit(void)

    printk("vaddr to paddr module is leaving..\n");
        vfree((void *)vaddr);
        free_page(vaddr);

    Get_pgtable_macro() 打印当前系统分页机制中的一些宏。

    通过vmalloc()在内核空间分配内存空间,调用vaddr2paddr()将虚拟地址转换为物理地址。

    通过使用 __get_free_pages () 在内核空间中分配帧,使用 vaddr2paddr () 将虚拟地址转换为物理地址。 分别通过vfree()和free_page()释放申请的内存空间。

Vaddr2paddr()执行如下:

    通过pgd_offset计算页面全局目录项的线性地址pgd,传入内存描述符mm和线性地址vaddr。接下来,打印pgd指向的页面全局目录条目。

    通过pud_offset计算页面父目录入口的线性地址pud,将参数传递给页面全局目录入口的线性地址pgd和线性地址vaddr。然后打印 pud 引用的父目录条目。

    通过pmd_offset计算页面中间目录入口的线性地址pmd,将参数传给父目录入口的线性地址pud和线性地址vaddr。然后打印页面中间提到的pmd目录条目。

    pte_offset_kernel pte_offset_kernel 由线性地址pte 计算,该参数为线性地址pmd 和线性地址vaddr 的目录项中间的地址。然后打印pte指向的页表项。

    pte_val(*pte) 删除页表项,和PAGE_MASK阶段,结果是访问页的物理地址; vaddr & ~ PAGE_MASK 用于获取线性地址偏移字段;两者还是最终的物理地址计算。

    打印物理地址

【讨论】:

以上是关于在delphi中如何获取字符串的内存地址的主要内容,如果未能解决你的问题,请参考以下文章

java String 内存地址问题?如何获取 String 内存地址!

用c语言如何获取内存地址?

WebAssembly:从 JavaScript 中的参数(带有内存地址)获取字符串的正确方法

如何获得java对象的内存地址

如何获取其他程序内存的地址,然后在我的程序中读取

linux内核 - 如何获取物理地址(内存管理)?