C程序中的分段错误

发布于 2024-10-07 10:45:47 字数 536 浏览 1 评论 0原文

只是为了测试我创建了以下代码:

#include<stdio.h>

int main(){
    char *p = "Hello world";
    *(p+1) = 'l';
    printf("%s", p);
    return 0;
}

但是当我在 ubuntu 10.04 下通过我的“gcc”编译器运行它时,我得到:

Segmentation fault

那么任何人都可以解释为什么会发生这种情况。

#include<stdio.h>
#include<stdlib.h>

int main(){
    char *p = malloc(sizeof(char)*100);
    p = "Hello world";
    *(p+1) = 'l';
    printf("%s", p);
    free(p);
    return 0;
}

这也会导致分段错误 提前致谢

just for testing i had created the following code:

#include<stdio.h>

int main(){
    char *p = "Hello world";
    *(p+1) = 'l';
    printf("%s", p);
    return 0;
}

But when i ran this over my "gcc" compiler under ubuntu 10.04 I got:

Segmentation fault

So can anyone explain this why this happened.

#include<stdio.h>
#include<stdlib.h>

int main(){
    char *p = malloc(sizeof(char)*100);
    p = "Hello world";
    *(p+1) = 'l';
    printf("%s", p);
    free(p);
    return 0;
}

this also cause a segmentation fault
Thanks in Advance

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

恬淡成诗 2024-10-14 10:45:47

char *p = "Hello world";
*(p+1) = 'l';

修改字符串文字的内容(即代码中的“Hello World”)是未定义行为。

ISO C99(第 6.4.5/6 节)

如果这些数组的元素具有适当的值,则这些数组是否不同是未指定的。 如果程序尝试修改此类数组,则行为未定义

尝试使用字符数组。

char p[] = "Hello World";
p[1] = 'l'; 

编辑

您修改的代码

#include<stdio.h>
#include<stdlib.h>
int main()
{
   char *p = malloc(sizeof(char)*100);
   p = "Hello world"; // p now points to the string literal, access to the dynamically allocated memory is lost.
   *(p+1) = 'l'; // UB as said before edits
   printf("%s", p);
   free(p); //disaster
   return 0;
}

也会调用未定义的行为,因为您试图释放尚未使用mallocfree) >

char *p = "Hello world";
*(p+1) = 'l';

Modiying the content of a string literal (i.e "Hello World" in your code) is Undefined Behavior.

ISO C99 (Section 6.4.5/6)

It is unspecified whether these arrays are distinct provided their elements have the appropriate values. If the program attempts to modify such an array, the behavior is undefined.

Try using array of characters.

char p[] = "Hello World";
p[1] = 'l'; 

EDIT

Your modified code

#include<stdio.h>
#include<stdlib.h>
int main()
{
   char *p = malloc(sizeof(char)*100);
   p = "Hello world"; // p now points to the string literal, access to the dynamically allocated memory is lost.
   *(p+1) = 'l'; // UB as said before edits
   printf("%s", p);
   free(p); //disaster
   return 0;
}

invokes Undefined Behaviour as well because you are trying to deallocate the section of memory (using free) which has not been allocated using malloc

眼波传意 2024-10-14 10:45:47

因为 char *p = "Hello world" 几乎肯定为您提供了一个指向只读内存的指针,这意味着尝试使用 *(p+1) = 'l' 更改它 是明确的禁忌(即使内存不是只读的,行为仍然是未定义的)。

C99 引用字符串文字的相关部分位于 6.4.5 para 6 中:

未指定这些数组是否不同,前提是它们的元素具有
适当的值。如果程序尝试修改这样的数组,则行为是
未定义。


仍然遇到类似以下情况的分段错误的原因

char *p = malloc (100);  // sizeof(char) is ALWAYS 1
p = "Hello";             // better would be: strcpy (p, "Hello")
*p = 'a';

是:即使您分配了允许修改的内存,第二个语句也会更改指针 指向一个字符串文字(当您无法访问已分配的内存时,会导致内存泄漏),并且不允许您对其进行修改。

您需要区分对指针的更改和对指针所指内容的更改。

Because char *p = "Hello world" has almost certainly given you a pointer to read-only memory and that means that trying to change it with *(p+1) = 'l' is a definite no-no (even if the memory isn't read-only, the behaviour is still undefined).

The relevant part of C99 referring to string literals is in 6.4.5 para 6:

It is unspecified whether these arrays are distinct provided their elements have the
appropriate values. If the program attempts to modify such an array, the behavior is
undefined.


The reason why you still get a segmentation fault with something like:

char *p = malloc (100);  // sizeof(char) is ALWAYS 1
p = "Hello";             // better would be: strcpy (p, "Hello")
*p = 'a';

is because, even though you're allocating memory which you're allowed to modify, the second statement changes the pointer to point to a string literal (giving you a mmory leak as you lose access to the allocated memory), which you are not allowed to modify.

You need to differentiate changes to the pointer from changes to what the pointer points at.

酒浓于脸红 2024-10-14 10:45:47

“Hello world” 是一个字符串文字。它由内存区域中的一个字节块表示,不能修改char *p 指向该字节块。 *(p+1) = 'l' 表示用“l”覆盖指向的字节之后的下一个字节。所指向的字节之后的下一个字节是不可修改的块的一部分。尝试覆盖某些内容就是尝试修改它。试图修改不允许修改的东西是非常糟糕的。

为了在内存中获得可以修改的文本副本,请将其放入数组中,例如char p[] = "Hello world";。 (请注意,以这种方式声明数组使其恰好足够大以容纳字符串,因此您可能不会延长它,因为没有更多空间。)

"Hello world" is a string literal. It is represented by a chunk of bytes in a region of memory which may not be modified. char *p points at that chunk of bytes. *(p+1) = 'l' says to overwrite the next byte after the pointed-at one with an 'l'. The next byte after the pointed-at one is part of the chunk which may not be modified. Attempting to overwrite something is attempting to modify it. Attempting to modify something which is not allowed to be modified is very bad.

In order to have a copy of the text in memory which may be modified, put it into an array, e.g. char p[] = "Hello world";. (Notice that declaring the array this way makes it exactly big enough to hold the string, and therefore you may not lengthen it, since there is no more room.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文