只要进程处于活动状态,const char* 文字字符串就会持久存在吗?

问题描述 投票:0回答:4

我有如下功能:

const char* get_message() {
    return "This is a constant message, will NOT change forever!";
};

const char* get_message2() {
    return "message2";
};

我计划在我的应用程序的任何地方使用它们,即使在不同的线程中。

我想知道这些字符串的生命周期,即在函数之外使用这些

const char*
字符串是否安全
get_message

我猜想硬编码的

const char*
字符串将被编译到应用程序的代码段而不是数据段中,所以也许像上面那样使用它们是安全的?

c++ constants constexpr lifetime null-terminated
4个回答
11
投票

从标准上给出答案,

"message"
是一个字符串文字,字符串文字具有静态生命周期,这意味着该对象(包含字符的
char const[]
)对整个程序都有生命周期。 (对于具有重要构造函数或析构函数的对象来说,情况要复杂一些)。因此指向它的指针在程序的生命周期内都有效。


8
投票

是的,这样做是安全的。你的假设是正确的。


6
投票

简短的答案是字符串文字“message2”将存在于内存中 与进程一样长,但在 .rodata 部分(假设我们谈论 ELF 文件)。

我们返回指向字符串常量的指针,但正如我们稍后将看到的,没有在存储此

const char *
指针的任何地方定义单独的内存 并且没有必要,因为字符串的地址是在代码中计算的,并在每次调用函数时使用寄存器 $rax 返回。

但是让我们看看代码中 gdb

发生了什么

我们在函数中放置断点,返回指向常量字符串的指针,我们看到汇编代码和流程图:

代码通过以下指令获取该字符串:

0x000055555555514a <+8>:    lea    0xeb3(%rip),%rax        # 0x555555556004

这条指令的作用是计算“message2”的地址。 我们在这里看到 PIC(位置无关代码)的含义。

“message2”字符串的地址未硬编码为绝对地址, 但计算为相对值,作为下一条指令地址的硬编码偏移 0xeb3 (0x555555555151 + 0xeb3) 并放入寄存器rax

相对寻址的目的(当前地址+/-偏移量) 意味着进程将始终获得“message2”的正确地址, 无论它加载到内存中的哪个位置。

所以在这里我们看到你问的

const char *
实际上并不存在于内存中,因为地址是“动态”计算并使用$rax返回的:

我们在 $rax 中有地址:

(gdb) i r $rax
rax   0x555555556004      93824992239620

它保存着“message2”的地址:

(gdb) x/s 0x555555556004
0x555555556004: "message2"

现在让我们看看地址0x555555556004在进程地址映射中的位置 是:

0x555555556000     0x555555557000     0x1000     0x2000  r--p   /home/drazen/proba/main

因此这部分不可执行且不可写,只是可读且私有(r--p),这是有道理的,因为这不是共享库。

当我们使用 readelf 检查时,它显示它位于 ELF 文件的 .rodata 部分:

drazen@HP-ProBook-640G1:~/proba$ readelf  -x .rodata main

Hex dump of section '.rodata':
0x00002000 01000200 6d657373 61676532 00       ....message2.

所以答案是这个字符串不会被硬编码在 ELF 文件的代码段 .text 中,而是只读数据段 .rodata,但是是的,当内存中存在长进程时,它会存在。

为了添加一些小细节,这个常量字符串当然会通过引用(地址)返回到 main() 函数,但不是在堆栈上,而是在寄存器中 rax:

(gdb) i r
rax   0x555555556004      93824992239620
rbx   0x0 

希望有帮助!


4
投票

我想知道这些字符串的生命周期,即在函数之外使用这些

const char*
字符串是否安全
get_message

快速浏览一下标准。

评估字符串文字会产生具有静态存储持续时间的字符串文字对象,该对象从上面指定的给定字符初始化。未指定所有字符串文字是否不同(即存储在不重叠的对象中)以及字符串文字的连续计算是否产生相同或不同的对象。 [注意:尝试修改字符串文字的效果未定义。 ——尾注]

----ISO/IEC JTC1 SC22 WG21 N4860(第 5.13.5 节 [字符串文字])

所以是的。在函数计算字符串文字并向字符串文字返回

const char*
后,标准确保该字符串文字将被赋予 静态存储持续时间

© www.soinside.com 2019 - 2024. All rights reserved.