【问题标题】:memcpy causes segfault after strstr succeedsstrstr 成功后 memcpy 导致 segfault
【发布时间】:2015-10-12 23:09:47
【问题描述】:

我试图创建一个函数,它将任何 URL 作为输入并从中删除 http://,然后从 URL 的其余部分获取 uri 和域。当我执行下面的代码时,我在 memcpy 语句中收到一个分段错误,标记为“//seg fault here”。

执行后,我收到以下输出:

TEST
http:// found
Segmentation fault

我预计会出现以下情况:

TEST
http:// found
/ found
www.x.com /a/b/c

当我声明一个大的缓冲区空间来复制结果时,为什么会收到分段错误?我的程序中是否存在导致指向结果的无效指针的内容?

代码如下:

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

void getdomurl(const char* in,char* uri,char* dom){
    char b[200000],*p=strstr(in,"http://");
    if (p){
        printf("http:// found\n");
        memcpy(b,p+7,100000); //seg fault here
    }else{
        printf("http:// not found\n");
        memcpy(b,in,100000);
    }
    printf("/ scan\n");
    p=strstr(b,"/");
    if (p){
        printf("/ found\n");
        memcpy(dom,b,p-b);memcpy(uri,p,100000);
    }else{
        printf("/ not found\n");
        memcpy(dom,b,100000);uri[0]='/';uri[1]='\0';
    }
}

int main(int argc,char* argv[]){
char uri[100000];char dom[10000];
printf("TEST\n");
getdomurl("http://www.x.com/a/b/c",uri,dom);
printf("%s %s",uri,dom);
return 0;
}

【问题讨论】:

    标签: c pointers segmentation-fault buffer


    【解决方案1】:

    虽然您已经为数组 b 明确分配了足够的内存,但您的输入字符串可能没有 100,000 字节。解决此问题的方法是使用查找空终止字符 strmcpy 的函数,而不是 memcpy。 http://www.cplusplus.com/reference/cstring/strncpy/

    strncpy(b,p+7,200000);
    

    也替换 memcpy 的其他 3 种用途。

    【讨论】:

    • 或者更好的是,使用 strncpy 来避免目标缓冲区溢出。
    • 好主意,我改用strncpy
    • 确实有效,这就是我接受它的原因,但我希望有一个好的 memcpy 解决方案或不会减慢程序速度的解决方案
    • strncpy 和 strstr 都寻找需要时间的终止字符,但它只是遍历字符串而已。如果您确实需要提高此算法的速度,可以使用特定于操作系统的函数来查找已分配内存块的大小。您的操作系统在某处存储分配的内存块表,对于极长的字符串,这些查找函数可能会更快,但您还必须通过查看前 7 个字符是否匹配“http://”来替换 strstr。
    【解决方案2】:

    p 被分配在in 中的一个位置,该位置包含一个比您要求memcpy 从中复制的100000 字节短得多的字符串文字。

    【讨论】:

      【解决方案3】:

      真的不需要memcpy(),因为整个工作都可以用指针来完成。这是我为自己的fetch 实用程序制作的粗略草图:

      #include <stdio.h>
      #include <string.h>
      void parseurl(char *argv)
      {
          char *host;
          char *type;
          char *page;
      
          type = host = page = argv;
          if ( (host = strstr(argv, "://")))
          {
              *host = '\0';
              host += 3;
          }
          else    
              return;
          if ((page = strstr(host, "/")))
              *page++ = '\0';
      
          printf("Attempting an [%s] protocol on [%s] to retrieve [%s]\n", type, host, page);
          /* fetch(type, host, page); */
          return;
      }
      
      /* "driver" */
      int main(int argc, char *argv[])
      { 
          if ( argc != 2 )
              return 1;
          parseurl(*++argv);
          return 0;
      }
      

      可以这样运行:

      ./parseurl http://www.google.com/index.html
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-08-25
        • 2010-12-25
        • 2011-11-29
        • 1970-01-01
        • 2014-10-13
        • 2020-02-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多