问题代码如下:

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

void parse(char* buf,char* args[])
{
  printf("buf=%s\n",buf);
  int i=0;
  while(*buf!='\0')
  {
    args[i]=buf;
    while((*buf!=' ')&&(*buf!='\t')&&(*buf!='\n')) buf++;
    while( (*buf==' ') || (*buf=='\t') || (*buf=='\n') )
    {
      *buf = '\0';  //注意本行
      buf++;
    }
    i++;
  }
  args[i]='\0';
  int j=0;
  while(j<i)
  {
    printf("arg[%d]=%s\n",j,args[j]);
    j++;
  }
  return;
}

int main()
{
  char* args[4];
  char buf[100]="a b c";  //-1-这里字符数组的定义有讲究
  parse(buf,args);
  execvp(*args,args);
  return 0;
}

 

-1-处的字符数组定义时需要注意,按照上面代码的代码定义并初始化没有问题,此时buf地址分配在非常量区,即非只读区,所以可以调用parse(buf,args)中的*buf='\0';

使用gdb查看此时堆栈结构:

Breakpoint 1, parse (buf=0x7fffffffe661 " b c", args=0x7fffffffe640) at parse.C:15
15 *buf = '\0';

 

但是如果此时这样定义:

  char* buf="a b c";

此时的buf分配在常量区,调用parse(buf,args)中的*buf='\0'时就会出现“Segmentation fault”,此时使用gdb查看出现错误的原因是:

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400629 in parse (buf=0x4007f3 " b c", args=0x7fffffffe640) at parse.C:15
15 *buf = '\0';

 

此时可以看到两次分配的buf的地址区域是不一样的,正确地址分配在非常量区(应该是在栈区),错误时分配在常量区;