C段错误
C segmentation fault
我正在尝试使用以下函数创建一个子数组:
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 的新手,所以我不知道是什么导致了这个异常。
我认为你的错误是你在测试中使用了 <=
,而它们应该是 <
。这将防止您 运行 离开数组的末尾。
这就是C难的原因。这是一个错误:您需要分配 (end-start+1)
项并在循环中使用 <=
。尝试改写成这样:
#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 习语和编程风格,它们会让您的生活变得更加轻松!
我正在尝试使用以下函数创建一个子数组:
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 的新手,所以我不知道是什么导致了这个异常。
我认为你的错误是你在测试中使用了 <=
,而它们应该是 <
。这将防止您 运行 离开数组的末尾。
这就是C难的原因。这是一个错误:您需要分配 (end-start+1)
项并在循环中使用 <=
。尝试改写成这样:
#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 习语和编程风格,它们会让您的生活变得更加轻松!