奇怪的 C 分段错误
Weird C segmentation fault
所以我有这段代码
int main(int argc, char *argv[]) {
char *vendas[1];
int size = 1;
int current = 0;
char buffer[50];
char *token;
FILE *fp = fopen("Vendas_1M.txt", "r");
while(fgets(buffer, 50, fp)) {
token = strtok(buffer, "\n");
if (size == current) {
*vendas = realloc(*vendas, sizeof(vendas[0]) * size * 2);
size *= 2;
}
vendas[current] = strdup(token);
printf("%d - %d - %s\n", current, size, vendas[current]);
current++;
}
}
事情是这样的...使用 GDB 它在
上给出了分段错误
vendas[current] = strdup(token);
但最奇怪的是它一直工作到 1024
的大小。大小增长到 1024
然后它只是在 1200 元素附近吐出一个分段错误。
我知道问题出在内存重新分配上,因为当我有一个静态数组时它起作用了。只是想不通。
您的 char *vendas[1]
数组中只有一 (1) 个指针的空间。所以第二次你超出了数组的限制并且处于未定义的行为领域。
此外,对 realloc
的第一次调用传递了一个未由 malloc
分配的指针,因此还有另一个未定义的行为。
您不能重新分配本地数组,您希望 vendas
成为指向已分配指针数组的指针:char **vendas = NULL;
.
您还应该包括正确的头文件并检查 fopen()
和 realloc()
失败。
这是修改后的版本:
#include <stdio.h>
#include <stdlib.h>
void free_array(char **array, size_t count) {
while (count > 0) {
free(array[--count]);
}
free(array);
}
int main(int argc, char *argv[]) {
char buffer[50];
char **vendas = NULL;
size_t size = 0;
size_t current = 0;
char *token;
FILE *fp;
fp = fopen("Vendas_1M.txt", "r");
if (fp == NULL) {
printf("cannot open file Vendas_1M.txt\n");
return 1;
}
while (fgets(buffer, sizeof buffer, fp)) {
token = strtok(buffer, "\n");
if (current >= size) {
char **savep = vendas;
size = (size == 0) ? 4 : size * 2;
vendas = realloc(vendas, sizeof(*vendas) * size);
if (vendas == NULL) {
printf("allocation failure\n");
free_array(savep, current);
return 1;
}
}
vendas[current] = strdup(token);
if (vendas[current] == NULL) {
printf("allocation failure\n");
free_array(vendas, current);
return 1;
}
printf("%d - %d - %s\n", current, size, vendas[current]);
current++;
}
/* ... */
/* free allocated memory (for cleanliness) */
free_array(vendas, current);
return 0;
}
所以我有这段代码
int main(int argc, char *argv[]) {
char *vendas[1];
int size = 1;
int current = 0;
char buffer[50];
char *token;
FILE *fp = fopen("Vendas_1M.txt", "r");
while(fgets(buffer, 50, fp)) {
token = strtok(buffer, "\n");
if (size == current) {
*vendas = realloc(*vendas, sizeof(vendas[0]) * size * 2);
size *= 2;
}
vendas[current] = strdup(token);
printf("%d - %d - %s\n", current, size, vendas[current]);
current++;
}
}
事情是这样的...使用 GDB 它在
上给出了分段错误vendas[current] = strdup(token);
但最奇怪的是它一直工作到 1024
的大小。大小增长到 1024
然后它只是在 1200 元素附近吐出一个分段错误。
我知道问题出在内存重新分配上,因为当我有一个静态数组时它起作用了。只是想不通。
您的 char *vendas[1]
数组中只有一 (1) 个指针的空间。所以第二次你超出了数组的限制并且处于未定义的行为领域。
此外,对 realloc
的第一次调用传递了一个未由 malloc
分配的指针,因此还有另一个未定义的行为。
您不能重新分配本地数组,您希望 vendas
成为指向已分配指针数组的指针:char **vendas = NULL;
.
您还应该包括正确的头文件并检查 fopen()
和 realloc()
失败。
这是修改后的版本:
#include <stdio.h>
#include <stdlib.h>
void free_array(char **array, size_t count) {
while (count > 0) {
free(array[--count]);
}
free(array);
}
int main(int argc, char *argv[]) {
char buffer[50];
char **vendas = NULL;
size_t size = 0;
size_t current = 0;
char *token;
FILE *fp;
fp = fopen("Vendas_1M.txt", "r");
if (fp == NULL) {
printf("cannot open file Vendas_1M.txt\n");
return 1;
}
while (fgets(buffer, sizeof buffer, fp)) {
token = strtok(buffer, "\n");
if (current >= size) {
char **savep = vendas;
size = (size == 0) ? 4 : size * 2;
vendas = realloc(vendas, sizeof(*vendas) * size);
if (vendas == NULL) {
printf("allocation failure\n");
free_array(savep, current);
return 1;
}
}
vendas[current] = strdup(token);
if (vendas[current] == NULL) {
printf("allocation failure\n");
free_array(vendas, current);
return 1;
}
printf("%d - %d - %s\n", current, size, vendas[current]);
current++;
}
/* ... */
/* free allocated memory (for cleanliness) */
free_array(vendas, current);
return 0;
}