Seg故障错误?

时间:2015-01-26 20:04:27

标签: c arrays string segmentation-fault void

有谁知道为什么我一直得到这个seg错误错误? 我正在尝试运行一个程序来定位一个子串"来自"在" src"并替换"中的所有非重叠事件。在src中"到"在输出字符串" dest"。 还有,有人能为我提供测试此案例的正确方法吗?因为我不太确定如何用类型" void" ...(尝试将其作为练习)来显示它

void find_replace(char* src, char* from, char* to, char* dest)
{
  int count = 0;
  int diff = strlen(to) - strlen(from);
  int destlength = strlen(src);
   dest = malloc(destlength);
  for (int i = 0; i < strlen(src); i++)
    {
      int index = 0;
      while (src[i+index] == from[index] && index < strlen(from)){
        index++;
      }
      if (index == strlen(from)) {
        for (int j = 0; j < strlen(to); j++) {
          dest[i+j+(count * diff)] = to[j];
        }
        i += strlen(from) - 1;
        count++;
      }
      else {
        dest[i + (count * diff)] = src[i];
      }
    }
  return ; 
}

是否足以为测试做到这一点?

int main (int argc, char *argv[])
{
     char* dest;
   find_replace("hello my name is leeho lim", "leeho lim", "(insert name)" dest);
  for (int i = 0; i < strlen(dest); i++)
    {
      printf("%c", dest[i]);
    }
  printf("\n");
}

3 个答案:

答案 0 :(得分:1)

问题发生的原因是您尝试使用

访问未分配的指针
strlen(dest)

在主程序中的for。

原因是你将指针dest的值发送给函数,而不是指针本身,所以当你在函数内部分配内存时,你实际上没有修改内存地址存储在它外面的指针中。

当您将指针作为函数的参数发送时,您实际在做的是发送存储在该指针中的内存地址,您发送的是存储在指针中的值,而不是指针本身。

如果你想获得字符串的已分配内存地址,你可以让函数返回它,或者你可以声明并发送dest作为pointer to a pointer

编辑:正如其他评论指出的那样,你也可以在main()中执行分配,而不是在你的功能中进行分配。

答案 1 :(得分:0)

您需要对程序进行一些小的调整。

find_replace的返回值更改为更改后的字符串的新分配内存。

而不是

void  find_replace(char* src, char* from, char* to, char* dest)

使用

char* find_replace(char* src, char* from, char* to)

稍微改变实施。

而不是

  dest = malloc(destlength);

使用

  char* dest = malloc(destlength);

而不是

  return;

使用

 return dest;

更改您使用该功能的方式。

而不是

char* dest;
find_replace("hello my name is leeho lim", "leeho lim", "(insert name)", dest);

使用

char* dest = find_replace("hello my name is leeho lim", "leeho lim", "(insert name)");

确保释放find_replace返回的内存。

free(dest);

这是一个完全有效的计划:

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

char* find_replace(char* src, char* from, char* to)
{
  int count = 0;
  int diff = strlen(to) - strlen(from);
  int destlength = strlen(src);
  char* dest = malloc(destlength);
  for (int i = 0; i < strlen(src); i++)
    {
      int index = 0;
      while (src[i+index] == from[index] && index < strlen(from)){
        index++;
      }
      if (index == strlen(from)) {
        for (int j = 0; j < strlen(to); j++) {
          dest[i+j+(count * diff)] = to[j];
        }
        i += strlen(from) - 1;
        count++;
      }
      else {
        dest[i + (count * diff)] = src[i];
      }
    }
  return dest; 
}

int main (int argc, char *argv[])
{
   char* dest = find_replace("hello my name is leeho lim", "leeho lim", "r sahu");
   for (int i = 0; i < strlen(dest); i++)
   {
      printf("%c", dest[i]);
   }
   free(dest);
   printf("\n");
}

更新,以回应OP的评论

如果find_replace的返回类型必须为void,则有关如何处理dest所需内存的几种选项。

  1. 在调用函数中为dest分配内存。

    char* dest = malloc(SUFFICIENT_SIZE);
    find_replace("hello my name is leeho lim", "leeho lim", "(insert name)", dest); 
    
    free(dest);
    

    然后,不需要行

    dest = malloc(...); 
    

    find_replace

  2. dest中为find_replace分配内存。然后,您需要将指针传递给指针。

    void find_replace(char* src, char* from, char* to, char** dest)
    

    并在函数中使用*dest而不只是dest

    void find_replace(char* src, char* from, char* to, char** dest)
    {
      int count = 0;
      int diff = strlen(to) - strlen(from);
      int destlength = strlen(src);
      *dest = malloc(destlength);
      for (int i = 0; i < strlen(src); i++)
        {
          int index = 0;
          while (src[i+index] == from[index] && index < strlen(from)){
            index++;
          }
          if (index == strlen(from)) {
            for (int j = 0; j < strlen(to); j++) {
              (*dest)[i+j+(count * diff)] = to[j];
            }
            i += strlen(from) - 1;
            count++;
          }
          else {
            (*dest)[i + (count * diff)] = src[i];
          }
        }
      return; 
    }
    

    并更改您的电话find_replace

    char* dest;
    find_replace("hello my name is leeho lim", "leeho lim", "(insert name)", &dest);
    

答案 2 :(得分:0)

您的(原始)代码存在两个主要问题:

  1. 它没有规定您的find_replace()函数将分配的目标缓冲区返回给调用者,并且
  2. 它无法为目标缓冲区可靠地分配足够的空间。
  3. 原则上,问题(1)可以通过两种方式解决。空间可以由调用者分配,并且指向它的指针传递给函数,或者空间可以由函数分配,并且指针返回给调用者。您的原始代码在函数中分配空间,但不会向调用者返回指向它的指针

    该功能最好执行分配,因为满足问题(2)需要对输入进行更彻底的分析,而不是坚持呼叫者执行。考虑一下修改后的代码中会发生什么:

    char dest[4];
    int canary = 0;
    
    find_replace("aaa", "a", "longer string", dest);
    assert(canary == 0);
    

    你最有可能得到一个段错误,可能你得到一个断言失败,也许你得到谁知道什么,因为find_replace()如果没有写过dest的结尾就无法完成它的工作,结果未定义。

    虽然您已经说过练习要求您的函数没有返回值(即void),但它仍然可以通过参数列表返回指向目标字符串的指针。您只需将指针传递给dest指针而不是其值,以便该函数可以更新该值。签名看起来像这样:

    void find_replace(const char *src, const char *from, const char *to,
                      char **dest_p);
    

    (请注意constsrcfrom的{​​{1}}个限定符,如果函数是接受字符串文字,则在适当的情况下(如果不是必需的话)是合适的。 )

    to所需的空间量是dest的长度加一个终结符加上,如果src长于to,则长度之间的差异fromto字符串的次数乘以from字符串的出现次数。但是,您可以计算该长度的上限,然后在找出实际使用的空间后缩小分配(如果需要)。例如:

    to

    实际的替换代码留作练习,毕竟 作业。