C 是什么导致此分段错误?书中的例子

C 是什么导致此分段错误?书中的例子,c,C,我正在阅读一本书,我尝试运行这个示例,但我收到一个分段错误-gdb说它是在设置argv[0]=filename时出现的 此代码直接从本书的可下载代码示例中复制/粘贴 #include <unistd.h> int main() { char filename[] = "/bin/sh\x00"; char **argv, **envp; // arrays that contain char pointers argv[0] = filename; // only a

我正在阅读一本书,我尝试运行这个示例,但我收到一个分段错误-gdb说它是在设置argv[0]=filename时出现的

此代码直接从本书的可下载代码示例中复制/粘贴

#include <unistd.h>

int main() {
  char filename[] = "/bin/sh\x00";
  char **argv, **envp; // arrays that contain char pointers

  argv[0] = filename; // only argument is filename - segmentation fault here
  argv[1] = 0;  // null terminate the argument array

  envp[0] = 0; // null terminate the environment array

  execve(filename, argv, envp);
}
#包括
int main(){
字符文件名[]=“/bin/sh\x00”;
char**argv,**envp;//包含char指针的数组
argv[0]=filename;//此处唯一的参数是filename-分段错误
argv[1]=0;//null终止参数数组
envp[0]=0;//null终止环境数组
execve(文件名、argv、envp);
}

编辑:乔恩·埃里克森(Jon Erickson)的《黑客:剥削的艺术》(Hacking:The Art of Exploration)一书获得了很好的评价。这个具体的例子被用作外壳代码部分中关于将C转换为机器代码的第一个教程,具体来说是exec_shell.C,可以从下载。我想,为了避免下面的一些负面评论,使用这段代码的一些上下文是必要的,很抱歉省略了细节,谢谢你的帮助。

这显然不是一本很好的书。问题是
argv
envp
都没有初始化,因此当您写入
argv[0]
时,您试图覆盖内存中的一些随机位置

试着这样做:

#include <unistd.h>

int main() {
  char *filename = "/bin/sh";
  char *argv[2], *envp[1];

  argv[0] = filename;
  argv[1] = 0;

  envp[0] = 0;

  execve(filename, argv, envp);
}

这显然不是一本很好的书。问题是
argv
envp
都没有初始化,因此当您写入
argv[0]
时,您试图覆盖内存中的一些随机位置

试着这样做:

#include <unistd.h>

int main() {
  char *filename = "/bin/sh";
  char *argv[2], *envp[1];

  argv[0] = filename;
  argv[1] = 0;

  envp[0] = 0;

  execve(filename, argv, envp);
}

char**argv


argv
指向不允许访问/写入的内存位置。它是一种更为人所知的字符**argv

argv
指向不允许访问/写入的内存位置。这是一种更好地称为

的东西,您从未分配要进入
argv
envp
的“指针数组”!哪本书遗漏了如此关键的步骤

在开始分配给
argv[0]
和朋友之前,可以添加
argv=malloc(2*sizeof(char*))
(对于
envp
),或者将
argv
envp
的声明更改为指针数组,而不是指向指针的指针(在本例中,后者是一种非常可行的方法,因为在编写代码时,您确实知道每个指针中需要多少个指针——因此动态分配有点超能力;-)。

您从不分配“指针数组”打算进入
argv
envp
!哪本书遗漏了如此关键的步骤


在开始分配给
argv[0]
和朋友之前,可以添加
argv=malloc(2*sizeof(char*))
(对于
envp
),或者将
argv
envp
的声明更改为指针数组,而不是指向指针的指针(在本例中,后者是一种非常可行的方法,因为在编写代码时,您确实知道每个指针中需要多少个指针——因此,动态分配在某种程度上是超权限的;-).

看起来你需要一本更好的书!在这个代码中,
argv
是一个没有分配存储空间的指针,指向随机内存(或者可能是
NULL
)。当你用
argv[0]去引用它时=…
,您的代码最终尝试写入随机内存。您的变量声明应该更像:

char *argv[3], *envp[1];

看起来你需要一本更好的书!在这个代码中,
argv
是一个没有分配存储空间的指针,指向随机内存(或者可能是
NULL
)。当你用
argv[0]解引用它时=…
,您的代码最终尝试写入随机内存。您的变量声明应该更像:

char *argv[3], *envp[1];

我不知道你从哪里得到这本书,但它显然很糟糕。
argv
是一个未初始化的指针,它包含一个随机地址。因此访问它很可能会导致访问冲突。

我不知道你从哪里得到这本书,但它显然很糟糕。
argv
是一个未初始化的指针指针,它持有一个随机地址。因此访问它很可能导致访问冲突。

在使用此类多级指针之前,我建议先阅读C中的动态内存分配

无论何时使用指针,都必须考虑是否需要为指针要指向的数据分配空间(对于多级指针,指针本身也是如此)

比如说,

char **bar; 
在这里,bar为一个指向指针的指针分配空间,即足够存储一个地址的空间。如果没有任何额外的数据分配,这是非常有用的

实际上,你应该做:

char **bar = calloc( 2 , sizeof(char *) );
这里,bar为指向指针的1个指针分配空间,也就是说,将一个地址存储为bar的空间,以及存储另外2个指针的2个连续位置,即bar[0]&bar

在这里,条[0]分配空间来存储大小为10-1的字符串(结尾为\0)

现在,如果执行字符串复制:

strcpy(bar[0],"Hello!");
最后的内存映射是:(地址以圆圈表示,内容以块表示)

在使用此类多级指针之前,我建议先阅读C中的动态内存分配

无论何时使用指针,都必须考虑是否需要为指针要指向的数据分配空间(对于多级指针,指针本身也是如此)

比如说,

char **bar; 
在这里,bar为一个指向指针的指针分配空间,即足够存储一个地址的空间。如果没有任何额外的数据分配,这是非常有用的

实际上,你应该做:

char **bar = calloc( 2 , sizeof(char *) );
在这里,bar为1个poi分配空间