所以我有一些C代码:

#include <stdio.h>
#include <string.h>

/* putting one of the "char*"s here causes a segfault */
void main() {
  char* path = "/temp";
  char* temp;
  strcpy(temp, path);
}

这样编译,运行和行为就像它看起来一样。但是,如果将一个或两个字符指针声明为全局变量,则strcpy会导致分段错误。为什么会这样?显然,我对范围的理解存在错误。

有帮助吗?

解决方案

正如其他海报所提到的,问题的根源是临时未初始化。当在堆栈上声明为自动变量时,它将包含该内存位置中发生的任何垃圾。显然,对于正在运行的编译器+ CPU + OS,该位置的垃圾是一个有效的指针。 strcpy“成功”因为它不是段错误,但实际上它将字符串复制到内存中其他位置的任意位置。这种内存损坏问题引起了各地C程序员的恐惧,因为它非常难以调试。

将temp变量声明移动到全局范围时,它将被置于BSS部分并自动归零。尝试取消引用* temp然后会导致段错误。

当您将* path移动到全局范围时,* temp会向上移动堆栈上的一个位置。该位置的垃圾显然不是有效的指针,因此取消引用* temp会导致段错误。

其他提示

temp变量不指向任何存储(内存),并且它未初始化。

如果temp被声明为 char temp [32]; ,那么无论在何处声明,代码都可以工作。但是,使用这样的固定大小来声明temp还有其他问题,但这是另一天的问题。

现在,为什么在全局声明而不是本地声明时会崩溃。运气...

当在本地声明时,temp的值来自当时堆栈上可能存在的值。幸运的是,它指向一个不会导致崩溃的地址。然而,它正在摧毁其他人使用的记忆。

当全局声明时,在大多数处理器上,这些变量将存储在将使用需求零页的数据段中。因此 char * temp 就像声明 char * temp = 0 一样。

你忘了分配和初始化temp:

temp = (char *)malloc(TEMP_SIZE);

确保TEMP_SIZE足够大。你也可以在运行时计算,然后确保大小足够(至少应该是strlen(path))

如上所述,您忘记为临时分配空间。 我更喜欢 strdup malloc + strcpy 。它做你想做的事。

不 - 无论变量如何,这都不起作用 - 它看起来就像是因为你得到了(非)幸运。您需要分配空间来存储字符串的内容,而不是保留未初始化的变量。

堆栈上未初始化的变量将指向几乎随机的内存位置。如果这些地址碰巧有效,那么你的代码将会在任何地方被践踏,但你不会收到错误(但可能会在代码中的其他地方出现令人讨厌的内存损坏相关错误)。

Globals始终失败,因为它们通常设置为指向未映射内存的特定模式。尝试取消引用这些会立即给你一个段错误(这更好 - 留待以后使得很难追踪错误)。

我想把第一个Adam的片段重写为

// Make temp a static array of 256 chars
char temp[256];
strncpy(temp, sizeof(temp), path);
temp[sizeof(temp)-1] = '\0';

那样你:

1. don't have magic numbers laced through the code, and
2. you guarantee that your string is null terminated.

第二点是丢失源字符串的最后一个字符,如果它>&gt; = 256个字符长。

需要注意的重要部分:
目标字符串dest必须足够大才能接收副本。
在你的情况下,temp没有分配内存来复制到。

从strcpy的手册页复制:

DESCRIPTION
   The  strcpy()  function  copies the string pointed to by src (including
   the terminating '\0' character) to the array pointed to by  dest.   The
   strings  may not overlap, and the destination string dest must be large
   enough to receive the copy.

您正在调用未定义的行为,因为您没有初始化 temp 变量。它指向内存中的随机位置,因此您的程序可能有效,但很可能会出现段错误。您需要将目标字符串作为数组,或者将其指向动态内存:

// Make temp a static array of 256 chars
char temp[256];
strncpy(temp, 256, path);

// Or, use dynamic memory
char *temp = (char *)malloc(256);
strncpy(temp, 256, path);

另外,使用 strncpy()代替 strcpy()以避免缓冲区溢出。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top