我是否误解了这个关于字符串文字范围的例子?
Do I misunderstand this example about scope of string literals?
我正在阅读常见的 C 陷阱,并在 some famous Uni website 上找到了这篇文章。 (这是 google 上出现的第二个 link。
该页面上的最后一个示例是,
// Memory allocation on the stack
void b(char **p) {
char * str="print this string";
*p = str;
}
int main(void) {
char * s;
b(&s);
s[0]='j'; //crash, since the memory for str is allocated on the stack,
//and the call to b has already returned, the memory pointed to by str
//is no longer valid.
return 0;
}
评论中的解释让我想到,字符串文字的内存不是静态的吗?
那里的实际错误不是您不应该修改字符串文字,因为它是未定义的行为吗?或者那里的评论是否正确,我对那个例子的理解是错误的?
进一步搜索后,我看到了这个问题:,我从那个问题中了解到,以下是有效代码。
#include <malloc.h>
char* a = NULL;
{
char* b = "Whosebug";
a = b;
}
int main() {
puts(a);
}
此外,这个 question 同意其他 Whosebug 问题和我的想法,但反对该网站代码的评论。
为了测试它,我尝试了以下方法,
#include <stdio.h>
#include <malloc.h>
void b(char **p)
{
char * str = "print this string";
*p = str;
}
int main(void)
{
char * s;
b(&s);
// s[0]='j'; //crash, since the memory for str is allocated on the stack,
//and the call to b has already returned, the memory pointed to by str is no longer valid.
printf("%s \n", s);
return 0;
}
正如预期的那样,不会出现分段错误。
字符串字面量通常放在 ELF
文件的 rodata
部分(只读),在 Linux\Windows\Mac-OS 下,它们最终会出现在一个内存区域中,该区域将生成写入时出现故障(加载时 OS 使用 MMU 或 MPU 配置)
不对,你误解了崩溃的原因。字符串文字具有静态持续时间,这意味着它们在程序的生命周期内存在。由于您的指针指向文字,因此您可以随时使用它。
崩溃的原因是字符串文字是只读的。事实上 char* x = ""
在 C++ 中是一个错误,因为它应该是 const char* x = ""
。从语言的角度来看,它们是只读的,任何修改它们的尝试都会导致未定义的行为。
实际上,它们通常放在只读段中,因此任何修改尝试都会触发 GPF - 一般保护错误。对 GPF 的通常响应是程序终止 - 这就是您在应用程序中看到的情况。
标准说(强调是我的):
6.4.5 String literals
[...] The multibyte character sequence is then used to initialize an array of static storage duration and length just sufficient to contain the sequence. [...]
[...] If the program attempts to
modify such an array, the behavior is undefined. [...]
我正在阅读常见的 C 陷阱,并在 some famous Uni website 上找到了这篇文章。 (这是 google 上出现的第二个 link。
该页面上的最后一个示例是,
// Memory allocation on the stack
void b(char **p) {
char * str="print this string";
*p = str;
}
int main(void) {
char * s;
b(&s);
s[0]='j'; //crash, since the memory for str is allocated on the stack,
//and the call to b has already returned, the memory pointed to by str
//is no longer valid.
return 0;
}
评论中的解释让我想到,字符串文字的内存不是静态的吗?
那里的实际错误不是您不应该修改字符串文字,因为它是未定义的行为吗?或者那里的评论是否正确,我对那个例子的理解是错误的?
进一步搜索后,我看到了这个问题:
#include <malloc.h>
char* a = NULL;
{
char* b = "Whosebug";
a = b;
}
int main() {
puts(a);
}
此外,这个 question 同意其他 Whosebug 问题和我的想法,但反对该网站代码的评论。
为了测试它,我尝试了以下方法,
#include <stdio.h>
#include <malloc.h>
void b(char **p)
{
char * str = "print this string";
*p = str;
}
int main(void)
{
char * s;
b(&s);
// s[0]='j'; //crash, since the memory for str is allocated on the stack,
//and the call to b has already returned, the memory pointed to by str is no longer valid.
printf("%s \n", s);
return 0;
}
正如预期的那样,不会出现分段错误。
字符串字面量通常放在 ELF
文件的 rodata
部分(只读),在 Linux\Windows\Mac-OS 下,它们最终会出现在一个内存区域中,该区域将生成写入时出现故障(加载时 OS 使用 MMU 或 MPU 配置)
不对,你误解了崩溃的原因。字符串文字具有静态持续时间,这意味着它们在程序的生命周期内存在。由于您的指针指向文字,因此您可以随时使用它。
崩溃的原因是字符串文字是只读的。事实上 char* x = ""
在 C++ 中是一个错误,因为它应该是 const char* x = ""
。从语言的角度来看,它们是只读的,任何修改它们的尝试都会导致未定义的行为。
实际上,它们通常放在只读段中,因此任何修改尝试都会触发 GPF - 一般保护错误。对 GPF 的通常响应是程序终止 - 这就是您在应用程序中看到的情况。
标准说(强调是我的):
6.4.5 String literals
[...] The multibyte character sequence is then used to initialize an array of static storage duration and length just sufficient to contain the sequence. [...]
[...] If the program attempts to modify such an array, the behavior is undefined. [...]