【问题标题】:Segmentation Fault when i do assign a value in an array in a funtion当我在函数的数组中分配值时出现分段错误
【发布时间】:2015-02-15 16:44:40
【问题描述】:

我确实调试了程序,当我执行 a[k] = a[h] 时,确实出现了分段错误。 数组a是一个动态数组,所以我不明白问题出在哪里...... 你能帮帮我吗?

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

void Invert(char* a, int k, int h) {
    if(k < h) {
        char app;
        app = a[k];
        a[k] = a[h]; //here is the error
        a[h] = app;
        Invert(a,k+1,h-1);
        }
}

void CallInvert(char* a, char k) {
    int n = strlen(a);
    Invert(a, k, n-1);
}


int main(int argc, char *argv[]) {
    char *a; int k,i;
    a = malloc(sizeof(char)*sizeof("Hi, how are you?"));
    a = "Hi, how are you?";
    k = 5;
    if(k>=strlen(a)) {
        printf("ERROR");
        return 0;
    }
    printf("Before: \"%s\"\n", a);
    CallInvert(a,k);
    printf("After: \"%s\"\n",a);
    free(a);
    return 0;
}

【问题讨论】:

  • a = "Hi, how are you?"; --> strcpy(a, "Hi, how are you?");
  • sizeof("Hi, how are you?") 这是错误的,而不是 sizeof 所做的。如果您需要字符串的长度,请使用strlen。你也不能像这里a = "Hi, how are you?";那样分配字符串
  • 但是如果一个do
    malloc = strlen("Hi, how are you")*sizeof(char)),它会忽略一个字符串最后一个字符的位置, '\0'。

标签: c arrays segmentation-fault malloc


【解决方案1】:

在 main() 中,a = "Hi, how are you?" 是错误的。您在此处分配一个指向常量字符串的指针。稍后当您尝试写入常量字符串时,它会崩溃(正如 iharob 在下面指出的那样,写入常量字符串更具体地称为导致“未定义行为”;这恰好是您平台中的分段错误)。

【讨论】:

  • 它不会崩溃,它是未定义的行为,可能的事情之一是分段错误。
  • 如果我做 'a[] = "嗨,你好吗?"'。我会犯同样的错误吗?
  • a[] = "hi, how are you?" 在 C 语法中无效,无法编译。您可以使用strcpy(a, "...")。请确保分配了足够大小的 a,包括终止的 0。
【解决方案2】:

您需要使用strcpy 函数。喜欢:

a = malloc(sizeof(char)*sizeof("Hi, how are you?"));
    strcpy(a ,"Hi, how are you?");

SEGFAULT 是因为你不能改变值常量字面量。

【讨论】:

    【解决方案3】:

    看看我对内存分配代码的改动:

        a = (char*)malloc(sizeof(char)* (sizeof("Hi, how are you?") + 1) );
        strcpy(a,"Hi, how are you?");
    

    sizeof("Hi, how are you?") 可以正常工作,但要存储'\0'(字符串结尾),您还需要一个字符。当然还有strcpystrncpy 用于将字符复制到可修改的内存中。

    【讨论】:

      【解决方案4】:

      我尝试执行了几次,没有发现你上面提到的那一行的问题,现在我的代码是这样的:

      #include <stdio.h>
      #include <stdlib.h>
      #include <string.h>
      
      void Invert(char* a, int k, int h) {
          if (k < h) {
              char app;
              app = a[k];
              a[k] = a[h];
              a[h] = app;
              Invert(a, k + 1, h - 1);
          }
      }
      
      void CallInvert(char* a, char k) {
          int n = strlen(a);
          Invert(a, k, n - 1);
      }
      
      int main(int argc, char *argv[]) {
          char *a = NULL; 
          int k;
          a = (char *)malloc(sizeof(char)*strlen("Hi, how are you?") + 1);
          strcpy(a, "Hi, how are you?");
          k = 5;
          if (k >= strlen(a)) {
              printf("ERROR");
              return 0;
          }
          printf("Before: \"%s\"\n", a);
          CallInvert(a, k);
          printf("After: \"%s\"\n", a);
          free(a);
          return 0;
      }
      

      它似乎工作正常并产生了输出:

      之前:“嗨,你好吗?”

      之后:“嗨,你好,哇”

      以下是我所做的一些更改:

      1. 使用strlen 获取字符串长度,使用strcpy 复制字符串,但我看到它有 已在评论中捕获,为了清楚起见,我将其留在这里。
      2. 将 malloc 的返回值类型转换为 char *,就像 Visual Studio 一样 抛出错误。这实际上取决于您是什么平台 继续运行。

      【讨论】:

      • 我正在使用代码块,所以我认为它是一样的。谢谢:D
      【解决方案5】:

      您的问题是由于将字符串文字分配给您的指针,它会覆盖malloc 返回的地址。这也意味着您对free 的调用将触发未定义的行为,例如段错误,因为您实际上是在这样做:

      char *a;
      a = "Hi, how are you?";
      free (a);
      

      您也无法释放malloc 返回指针的内存。这意味着您有内存泄漏。

      正如其他人所说,您想使用strcpy复制字符串:

      a = malloc (sizeof "Hi, how are you?");
      strcpy (a, "Hi, how are you?");
      

      那么事情应该可以正常工作了。

      忽略在这种情况下不知道如何使用sizeof 的人。直到现在,他们可能还不知道,字符串文字被认为是一个字符数组,加上 1 个用于空终止符的额外字符槽,而不仅仅是指向此类数组的指针。您可以使用strlen 并根据需要将其加1,但是当您嵌入空字符时会失败,这与sizeof 运算符不同:

      #define HELLO "Hello\0World!"
      printf (
          "%zu\n%zu\n",
          sizeof HELLO,
          strlen (HELLO) + 1
      );
      

      另外,我只是不喜欢调用一个函数并执行算术,因为编译器可以为我做这件事而没有这种开销。

      但是,一旦将字符串文字分配给指针,就会删除任何大小信息,这可能是对sizeof 和字符串文字的误解的来源。在这种情况下,使用strlen 更安全。公平地说,我不知道有任何代码实际上将空字符嵌入到作为sizeof 运算符的操作数的字符串文字中。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-06-08
        • 2020-08-02
        • 2013-11-08
        • 2022-09-23
        • 2021-06-09
        • 2021-07-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多