崩溃或分段故障'当数据复制/扫描/读取到非初始化的指针时

发布于 2025-02-11 16:23:26 字数 419 浏览 3 评论 0 原文

这个问题应用作所有常见性问题的参考:

当我将/复制/扫描数据分配到非初始化指针的地址时,为什么我会得到意外的行为,通常是神秘的崩溃或“分段错误”指向?

示例:

int *ptr;
*ptr = 10; // Crash here!
char *ptr;
strcpy(ptr, "Hello, World!"); // Crash here!
char *ptr;
scanf("%s", ptr); // Crash here!

This question is meant to be used as reference for all frequently asked questions of the nature:

Why do I get unexpected behavior, usually a mysterious crash or 'segmentation fault,' when I assign/copy/scan data to the address where an uninitialized pointer points to?

Examples:

int *ptr;
*ptr = 10; // Crash here!
char *ptr;
strcpy(ptr, "Hello, World!"); // Crash here!
char *ptr;
scanf("%s", ptr); // Crash here!

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

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

发布评论

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

评论(5

耳根太软 2025-02-18 16:23:26

指针是一种特殊类型的变量,它只能包含另一个变量的地址。它不能包含任何数据。您不能“将/存储数据复制到指针中” - 这没有任何意义。您只能将指针设置为指向其他地方分配的数据。

这意味着,为了使指针有意义,它必须始终指向有效的内存位置。例如,它可以指向堆栈上分配的内存:

{
  int data = 0;
  int* ptr = &data;
  ...
}

或在堆上动态分配的内存:

int* ptr = malloc(sizeof(int));

在初始化指针之前,使用指针始终是一个错误。它尚未指向有效的内存。

这些示例都可能导致程序崩溃或其他类型的意外行为,例如“分割故障”:

/*** examples of incorrect use of pointers ***/

// 1.
int* bad;
*bad = 42;

// 2.
char* bad;
strcpy(bad, "hello");

相反,您必须确保指针指向(足够)分配的内存:

/*** examples of correct use of pointers ***/

// 1.
int var;
int* good = &var;
*good = 42;

// 2.
char* good = malloc(5 + 1); // allocates memory for 5 characters *and*  the null terminator
strcpy(good, "hello");

请注意,您还可以将指点设置为指向通过让其指向 null ,定义明确的“无处”。这使其成为 null指针,这是一个指针,可以保证不要指向任何有效的内存。这与使指针完全非专业化不同。

int* p1 = NULL; // pointer to nowhere
int* p2;        // uninitialized pointer, pointer to "anywhere", cannot be used yet

但是,如果您尝试访问由空指针指向的内存,则可能会遇到类似的问题,就像使用非初始化的指针:崩溃或分段故障一样。在最好的情况下,您的系统会注意到您正在尝试访问地址为空,然后引发“无效指针异常”。

NULL指针异常错误的解决方案是相同的:您必须将指针设置为在使用之前指向有效内存。


进一步阅读:

指向无效数据的指针
如何使用Pointers从其他函数中访问本地变量?

可以在其范围之外访问局部变量的内存吗?<<<<<<<<<<<<<<<<<<<< /a>

分割故障和原因
什么是分段故障?
为什么要这样做当写作用“ char *s”初始化的字符串时,我会得到一个细分错误,但不是“ char s []”?
char s [ ]和char *s?
确定的分割故障的常见原因列表

A pointer is a special type of variable, which can only contain an address of another variable. It cannot contain any data. You cannot "copy/store data into a pointer" - that doesn't make any sense. You can only set a pointer to point at data allocated elsewhere.

This means that in order for a pointer to be meaningful, it must always point at a valid memory location. For example it could point at memory allocated on the stack:

{
  int data = 0;
  int* ptr = &data;
  ...
}

Or memory allocated dynamically on the heap:

int* ptr = malloc(sizeof(int));

It is always a bug to use a pointer before it has been initialized. It does not yet point at valid memory.

These examples could all lead to program crashes or other kinds of unexpected behavior, such as "segmentation faults":

/*** examples of incorrect use of pointers ***/

// 1.
int* bad;
*bad = 42;

// 2.
char* bad;
strcpy(bad, "hello");

Instead, you must ensure that the pointer points at (enough) allocated memory:

/*** examples of correct use of pointers ***/

// 1.
int var;
int* good = &var;
*good = 42;

// 2.
char* good = malloc(5 + 1); // allocates memory for 5 characters *and*  the null terminator
strcpy(good, "hello");

Note that you can also set a pointer to point at a well-defined "nowhere", by letting it point to NULL. This makes it a null pointer, which is a pointer that is guaranteed not to point at any valid memory. This is different from leaving the pointer completely uninitialized.

int* p1 = NULL; // pointer to nowhere
int* p2;        // uninitialized pointer, pointer to "anywhere", cannot be used yet

Yet, should you attempt to access the memory pointed at by a null pointer, you can get similar problems as when using an uninitialized pointer: crashes or segmentation faults. In the best case, your system notices that you are trying to access the address null and then throws a "null pointer exception".

The solution for null pointer exception bugs is the same: you must set the pointer to point at valid memory before using it.


Further reading:

Pointers pointing at invalid data
How to access a local variable from a different function using pointers?
Can a local variable's memory be accessed outside its scope?

Segmentation fault and causes
What is a segmentation fault?
Why do I get a segmentation fault when writing to a string initialized with "char *s" but not "char s[]"?
What is the difference between char s[] and char *s?
Definitive List of Common Reasons for Segmentation Faults
What is a bus error?

梦忆晨望 2025-02-18 16:23:26
  1. 指针仅指向内存位置。您创建了一个指针,但还没有绑定到内存位置。 strcpy 希望您通过两个指示器(第一个指向必须是constand ),指向两个字符阵列,如此签名:

      char * strcpy(char *目的地,const char * source);
     

    示例用法:

      char* ptr = malloc(32);  
    strcpy(PTR,“ Hello World”);
     
      char str [32];  
    Strcpy(Str,“ Hello World”);
     
  2. 您可以尝试尝试以下代码段以读取字符串直到达到newline字符(*您还可以添加其他空格字符,例如“%[^\ t \ n] s“ ”( tab,newline )或“%[^ \ t \ n] s“ space,tab,newline ))。

      char *ptr = malloc(32);
    scanf(“%31 [^\ n]”,ptr);
     

    (在现实生活中,不要忘记从 scanf()!!)

    检查返回值,

  1. Pointers only point to a memory location. You created a pointer but you did not bind to a memory location yet. strcpy wants you to pass two pointers (first one mustn't be constant) that point to two character arrays like this signature:

    char * strcpy ( char * destination, const char * source );
    

    sample usage:

    char* ptr = malloc(32);  
    strcpy(ptr, "hello world");
    
    char str[32];  
    strcpy(str, "hello world");
    
  2. You can try the following code snippet to read string until reaching newline character (*you can also add other whitespace characters like "%[^\t\n]s"(tab, newline) or "%[^ \t\n]s" (space, tab, newline)).

    char *ptr = malloc(32);
    scanf("%31[^\n]", ptr);
    

    (In real life, don't forget to check the return value from scanf()!)

最佳男配角 2025-02-18 16:23:26

学习C时经常发生的一种情况正在尝试使用单个引号来表示字符串文字:

char ptr[5];
strcpy(ptr, 'hello'); // crash here!
//            ^     ^   because of ' instead of "

在C,'H'是单个字符的文字,而“ H” 是包含'H'的字符串字符串和null终结者 \ 0 (即2个char数组)。另外,在C中,字符的类型是 int ,即 sizeof('h')等于 sizef(int),而 sizeof(char) 1

char h = 'h';
printf("Size: %zu\n", sizeof(h));     // Size: 1
printf("Size: %zu\n", sizeof('h'));   // likely output: Size: 4

One situation that frequently occurs while learning C is trying to use single quotes to denote a string literal:

char ptr[5];
strcpy(ptr, 'hello'); // crash here!
//            ^     ^   because of ' instead of "

In C, 'h' is a single character literal, while "h" is a string literal containing an 'h' and a null terminator \0 (that is, a 2 char array). Also, in C, the type of a character literal is int, that is, sizeof('h') is equivalent to sizeof(int), while sizeof(char) is 1.

char h = 'h';
printf("Size: %zu\n", sizeof(h));     // Size: 1
printf("Size: %zu\n", sizeof('h'));   // likely output: Size: 4
¢蛋碎的人ぎ生 2025-02-18 16:23:26

为了制作字符串的可修改副本,而不是使用 malloc strlen strcpy ,POSIX C库具有一个方便的功能,称为 strdup &lt; string.h&gt; 中,该>将返回带有分配的存储持续时间的传递的null终止字符串的副本。使用后,应使用免费发布指针:

char* ptr;
ptr = strdup("hello world");
ptr[0] = 'H';
puts(ptr);
free(ptr);

For making a modifiable copy of a string, instead of using malloc, strlen and strcpy, the POSIX C library has a handy function called strdup in <string.h> that will return a copy of the passed-in null-terminated string with allocated storage duration. After use the pointer should be released with free:

char* ptr;
ptr = strdup("hello world");
ptr[0] = 'H';
puts(ptr);
free(ptr);
可是我不能没有你 2025-02-18 16:23:26

发生这种情况是因为您没有为 Pointer char* pr* ptr 分配内存。
在这种情况下,您必须为指针分配内存。一种方法是使用functions malloc() and calloc()

char* ptr;
ptr = malloc(50); // Allocate space for 50 characters
strcpy(ptr, "hello world");

当使用**时, 动态分配内存。 ptr 不要忘记分配给*ptr deallocation memory 。这可以使用 free()函数完成。

free(ptr); // Deallocating memory
// Size of dynamically allocated memory can be changed by using realloc()

char *tmp = realloc(ptr, 100); // Allocate space for 100 characters
if (!tmp) {
    // Reallocation failed, ptr not freed
    perror("Resize failed");
    exit(1);       
}
else {
    // Reallocation succeeded, old ptr freed
    ptr = tmp;
}

在大多数情况下,由于内存分配中的错误阵列中的误差发生在结合情况下。

This happens because you have not allocated memory for the pointer char* ptr.
In this case you have to allocate memory for the pointer. One way to do this is to dynamically allocate memory using the functions malloc() and calloc():

char* ptr;
ptr = malloc(50); // Allocate space for 50 characters
strcpy(ptr, "hello world");

When the use of *ptr over don't forget to deallocate memory allocated for *ptr. This can be done using free() function.

free(ptr); // Deallocating memory
// Size of dynamically allocated memory can be changed by using realloc()

char *tmp = realloc(ptr, 100); // Allocate space for 100 characters
if (!tmp) {
    // Reallocation failed, ptr not freed
    perror("Resize failed");
    exit(1);       
}
else {
    // Reallocation succeeded, old ptr freed
    ptr = tmp;
}

In most cases segmentation fault happens due to error in memory allocation or array out of bound cases.

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