【问题标题】:C segmentation faultC 分段错误
【发布时间】:2016-09-18 22:16:15
【问题描述】:

我正在尝试使用以下函数创建一个子数组:

Track * subArray(Track * arr, int start, int end){
   int size = end - start;

   Track * t = malloc(sizeof(Track) * size);

      for(int i = 0; i < size && start <= end; i++){
          t[i] = arr[start++];

      } 
}

t 指针的大小始终为 8,即使我不将它与 size 相乘,我也会遇到分段错误。我是 C 新手,所以我不知道是什么导致了这个异常。

【问题讨论】:

  • i &lt;= size -->> i &lt; size
  • int size = end - start; --> int size = end - start + 1;
  • 或者那个,取决于语义。
  • 同样subArray必须返回值。
  • @MerveSahin pointer 总是相同的大小,因为它只是:一个指针,或者内存中的一个单元(你显然是在 64 位机器上) )。它指向 to 的东西会有所不同。这就是为什么你将sizeof(Track) 乘以大小。

标签: c segmentation-fault malloc sizeof


【解决方案1】:

这就是 C 语言难的原因。这是一个错误:您需要分配(end-start+1) 项目并在循环中使用&lt;=。尝试改写成这样:

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

typedef struct Track {
  char* color;
} Track;

Track * subArray(Track* arr, int start, int end){
  assert(end > start);

  const int size = 1 + end - start;
  printf("Allocating %d items\n", size);    
  Track* t = malloc(sizeof(Track)*size);

  for(int i=start; i <= end; ++i) {
    printf("at %d fetching %d\n", i-start, i);
    t[i-start] = arr[i];
  }

  return t;
}

int main() {
  Track *track = malloc(sizeof(Track) * 7);
  track[0].color = "red";
  track[1].color = "orange";
  track[2].color = "yellow";
  track[3].color = "blue";
  track[4].color = "indigo";
  track[5].color = "green";
  track[6].color = "violet";

  Track *sub = subArray(track, 3, 5);
  printf("%s\n", sub[0].color);
  printf("%s\n", sub[1].color);
  printf("%s\n", sub[2].color);
}

编译运行:

$ cc -g -W -Wall a.c && ./a.out
Allocating 3 items
at 0 fetching 3
at 1 fetching 4
at 2 fetching 5
blue
indigo
green

请注意,我在这里复制了char* 指针的值。这可能会导致更多令人困惑的内容,以防万一您考虑复制我的代码(我刚刚起草了一些可以说明问题的内容)。

更新

您正在使用包容性索引。然而,在 C 中,指定起始索引和长度是很常见的。许多标准库函数都这样做,这是您最有可能在生产代码中看到的。一个原因可能是它更容易推理。在您的情况下,代码将是

Track* subArray(Track* arr, const size_t start, const size_t length) {
  Track* t = malloc(sizeof(Track) * length);

  for (size_t i = 0; i < length; ++i)
    t[i] = arr[i + start];

  return t;
}

相应的调用将是

Track *sub = subArray(track, 3, 3);

在我看来,这不仅更好看;它更简单,更容易理解。

另一件常见的事情是复制指针而不是整个结构。这将取决于您的代码和数据结构的组织方式。在这种情况下,在指针数组的末尾使用哨兵值来标记其结束是很常见的:这通常是一个 NULL 指针。

继续练习并继续阅读其他人的代码,您很快就会发现 C 习语和编程风格,它们会让您的生活变得更轻松!

【讨论】:

    【解决方案2】:

    我认为你的错误是你在测试中使用了&lt;=,而它们应该是&lt;。这将防止您耗尽阵列的末端。

    【讨论】:

      猜你喜欢
      • 2017-08-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多