无法到达 realloc 分配的内存
Can't reach memory allocated by realloc
我有一个全局动态指针数组 (iterator
) 指向结构 (person_t
)。首先,我为 iterator
分配了 10*sizeof(person_t*)
内存,在内部我为每个 iterator[i]
i = 0..9
.
分配了 sizeof(person_t)
内存
typedef struct Person
{
char name[30];
unsigned age;
char job[30];
} person_t;
person_t **iterator;
int size = 10;
int count = 0;
int main()
{
int i;
iterator = malloc(size * sizeof(person_t *));
if (iterator == NULL)
{
/*fprintf(stderr, "Memory allocation did not succeed\n");*/
exit(1);
}
for (i = 0; i < size; ++i)
{
iterator[i] = malloc(sizeof(person_t));
if (iterator[i] == NULL)
{
/*fprintf(stderr, "Memory allocation did not succeed\n");*/
exit(1);
}
}
}
在我达到最大容量之前一切正常。发生这种情况时,我尝试重新分配 iterator
以获得更多内存,但它似乎不起作用,尽管我没有收到任何类型的警告或编译错误(我使用 gcc -ansi -pedantic -W -Wall -Wextra
编译),并且 realloc 不会 return NULL。这就是一切发生的地方:
void grow()
{
int i;
size += 5;
iterator = realloc(iterator, size);
if (iterator == NULL)
{
/*fprintf(stderr, "Memory allocation did not succeed\n");*/
exit(1);
}
printf("realloced to bigger\n");
for (i = size - 5; i < size; ++i)
{
iterator[i] = malloc(sizeof(person_t));
if (iterator[i] == NULL)
{
/*fprintf(stderr, "Memory allocation did not succeed\n");*/
exit(1);
}
}
}
当我尝试在调用 grow()
之前列出我的数据时,一切都很好。在 grow()
之后,可能会打印前 3 个结构(第一个被搞砸了),然后我得到 Segmentation fault
.
如果有帮助,这里是完整代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Person
{
char name[30];
unsigned age;
char job[30];
} person_t;
person_t **iterator;
int size = 10;
int count = 0;
void newPerson();
void grow();
void list();
void del();
int main()
{
int i;
iterator = malloc(size * sizeof(person_t *));
if (iterator == NULL)
{
/*fprintf(stderr, "Memory allocation did not succeed\n");*/
exit(1);
}
for (i = 0; i < size; ++i)
{
iterator[i] = malloc(sizeof(person_t));
if (iterator[i] == NULL)
{
/*fprintf(stderr, "Memory allocation did not succeed\n");*/
exit(1);
}
}
while (1)
{
char menuChoice = ' ';
scanf("%c", &menuChoice);
switch (menuChoice)
{
case 'a':
newPerson();
break;
case 'l':
list();
break;
case 'x':
for (i = 0; i < size; ++i)
{
free(iterator[i]);
}
free(iterator);
exit(0);
case 'd':
del();
break;
case '\n':
break;
default:
fprintf(stderr, "\'a\' -add, \'l\' -list, \'d\' -delete, \'x\' -exit\nOnly these inputs are allowed\n");
break;
}
}
return 0;
}
void newPerson()
{
unsigned a = 0;
char strN[30];
char strJ[30];
int err;
if (count == size)
grow();
/*printf("Name: ");*/
scanf("%s", strN);
if ((strlen(strN) + 1) > 30)
{
do
{
fprintf(stderr, "Maximum 30 characters are allowed\n");
scanf("%s", strN);
} while ((strlen(strN) + 1) > 30);
}
/*printf("Age: ");*/
err = scanf("%u", &a);
if (err != 1)
{
do
{
printf("Only numbers are allowed\n");
fgetc(stdin);
err = scanf("%u", &a);
} while (err != 1);
}
/*printf("Job: ");*/
scanf("%s", strJ);
if ((strlen(strJ) + 1) > 30)
{
do
{
fprintf(stderr, "Maximum 30 characters are allowed\n");
scanf("%s", strJ);
} while ((strlen(strJ) + 1) > 30);
}
iterator[count]->age = a;
strcpy(iterator[count]->name, strN);
strcpy(iterator[count]->job, strJ);
count++;
}
void list()
{
int i;
for (i = 0; i < count; ++i)
{
printf("%d. person:\tname: %s, age: %d, job: %s\n", i + 1, iterator[i]->name, iterator[i]->age, iterator[i]->job);
}
}
void grow()
{
int i;
size += 5;
iterator = realloc(iterator, size);
if (iterator == NULL)
{
/*fprintf(stderr, "Memory allocation did not succeed\n");*/
exit(1);
}
printf("realloced to bigger\n");
for (i = size - 5; i < size; ++i)
{
iterator[i] = malloc(sizeof(person_t));
if (iterator[i] == NULL)
{
/*fprintf(stderr, "Memory allocation did not succeed\n");*/
exit(1);
}
}
}
void del()
{
char toDelete[30];
int i;
int toDeleteIndex;
scanf("%s", toDelete);
if ((strlen(toDelete) + 1) > 30)
{
do
{
fprintf(stderr, "Maximum 30 characters are allowed\n");
scanf("%s", toDelete);
} while ((strlen(toDelete) + 1) > 30);
}
for (i = 0; i < count; ++i)
{
if (strcmp(iterator[i]->name, toDelete) == 0)
{
toDeleteIndex = i;
}
}
if (i == count)
{
fprintf(stderr, "No match\nBack to menu\n");
}
else
{
free(iterator[toDeleteIndex]);
for (i = toDeleteIndex; i < count - 1; ++i)
{
iterator[i] = iterator[i + 1];
}
free(iterator[count]);
count--;
if (count == size - 6)
{
size -= 5;
iterator = realloc(iterator, size);
if (iterator == NULL)
{
/*fprintf(stderr, "Memory allocation did not succeed\n");*/
exit(1);
}
printf("realloced to smaller\n");
}
}
}
正如在malloc
中一样,您需要以字节为单位指定大小。例如:
v = realloc(iterator, size * sizeof *iterator);
if( v != NULL ){
iterator = v;
}
这是一个常见错误,可能是选择“尺寸”以外名称的一个很好的理由。 (也许称之为“能力”)。
请注意,尽管在您的代码中执行 iterator = realloc(iterator, size * sizeof *iterator)
是可以的,因为如果 realloc returns NULL,您会立即中止程序,但我修改了代码以使用不同的变量,只是为了向未来的读者强调该代码模式。
我有一个全局动态指针数组 (iterator
) 指向结构 (person_t
)。首先,我为 iterator
分配了 10*sizeof(person_t*)
内存,在内部我为每个 iterator[i]
i = 0..9
.
sizeof(person_t)
内存
typedef struct Person
{
char name[30];
unsigned age;
char job[30];
} person_t;
person_t **iterator;
int size = 10;
int count = 0;
int main()
{
int i;
iterator = malloc(size * sizeof(person_t *));
if (iterator == NULL)
{
/*fprintf(stderr, "Memory allocation did not succeed\n");*/
exit(1);
}
for (i = 0; i < size; ++i)
{
iterator[i] = malloc(sizeof(person_t));
if (iterator[i] == NULL)
{
/*fprintf(stderr, "Memory allocation did not succeed\n");*/
exit(1);
}
}
}
在我达到最大容量之前一切正常。发生这种情况时,我尝试重新分配 iterator
以获得更多内存,但它似乎不起作用,尽管我没有收到任何类型的警告或编译错误(我使用 gcc -ansi -pedantic -W -Wall -Wextra
编译),并且 realloc 不会 return NULL。这就是一切发生的地方:
void grow()
{
int i;
size += 5;
iterator = realloc(iterator, size);
if (iterator == NULL)
{
/*fprintf(stderr, "Memory allocation did not succeed\n");*/
exit(1);
}
printf("realloced to bigger\n");
for (i = size - 5; i < size; ++i)
{
iterator[i] = malloc(sizeof(person_t));
if (iterator[i] == NULL)
{
/*fprintf(stderr, "Memory allocation did not succeed\n");*/
exit(1);
}
}
}
当我尝试在调用 grow()
之前列出我的数据时,一切都很好。在 grow()
之后,可能会打印前 3 个结构(第一个被搞砸了),然后我得到 Segmentation fault
.
如果有帮助,这里是完整代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Person
{
char name[30];
unsigned age;
char job[30];
} person_t;
person_t **iterator;
int size = 10;
int count = 0;
void newPerson();
void grow();
void list();
void del();
int main()
{
int i;
iterator = malloc(size * sizeof(person_t *));
if (iterator == NULL)
{
/*fprintf(stderr, "Memory allocation did not succeed\n");*/
exit(1);
}
for (i = 0; i < size; ++i)
{
iterator[i] = malloc(sizeof(person_t));
if (iterator[i] == NULL)
{
/*fprintf(stderr, "Memory allocation did not succeed\n");*/
exit(1);
}
}
while (1)
{
char menuChoice = ' ';
scanf("%c", &menuChoice);
switch (menuChoice)
{
case 'a':
newPerson();
break;
case 'l':
list();
break;
case 'x':
for (i = 0; i < size; ++i)
{
free(iterator[i]);
}
free(iterator);
exit(0);
case 'd':
del();
break;
case '\n':
break;
default:
fprintf(stderr, "\'a\' -add, \'l\' -list, \'d\' -delete, \'x\' -exit\nOnly these inputs are allowed\n");
break;
}
}
return 0;
}
void newPerson()
{
unsigned a = 0;
char strN[30];
char strJ[30];
int err;
if (count == size)
grow();
/*printf("Name: ");*/
scanf("%s", strN);
if ((strlen(strN) + 1) > 30)
{
do
{
fprintf(stderr, "Maximum 30 characters are allowed\n");
scanf("%s", strN);
} while ((strlen(strN) + 1) > 30);
}
/*printf("Age: ");*/
err = scanf("%u", &a);
if (err != 1)
{
do
{
printf("Only numbers are allowed\n");
fgetc(stdin);
err = scanf("%u", &a);
} while (err != 1);
}
/*printf("Job: ");*/
scanf("%s", strJ);
if ((strlen(strJ) + 1) > 30)
{
do
{
fprintf(stderr, "Maximum 30 characters are allowed\n");
scanf("%s", strJ);
} while ((strlen(strJ) + 1) > 30);
}
iterator[count]->age = a;
strcpy(iterator[count]->name, strN);
strcpy(iterator[count]->job, strJ);
count++;
}
void list()
{
int i;
for (i = 0; i < count; ++i)
{
printf("%d. person:\tname: %s, age: %d, job: %s\n", i + 1, iterator[i]->name, iterator[i]->age, iterator[i]->job);
}
}
void grow()
{
int i;
size += 5;
iterator = realloc(iterator, size);
if (iterator == NULL)
{
/*fprintf(stderr, "Memory allocation did not succeed\n");*/
exit(1);
}
printf("realloced to bigger\n");
for (i = size - 5; i < size; ++i)
{
iterator[i] = malloc(sizeof(person_t));
if (iterator[i] == NULL)
{
/*fprintf(stderr, "Memory allocation did not succeed\n");*/
exit(1);
}
}
}
void del()
{
char toDelete[30];
int i;
int toDeleteIndex;
scanf("%s", toDelete);
if ((strlen(toDelete) + 1) > 30)
{
do
{
fprintf(stderr, "Maximum 30 characters are allowed\n");
scanf("%s", toDelete);
} while ((strlen(toDelete) + 1) > 30);
}
for (i = 0; i < count; ++i)
{
if (strcmp(iterator[i]->name, toDelete) == 0)
{
toDeleteIndex = i;
}
}
if (i == count)
{
fprintf(stderr, "No match\nBack to menu\n");
}
else
{
free(iterator[toDeleteIndex]);
for (i = toDeleteIndex; i < count - 1; ++i)
{
iterator[i] = iterator[i + 1];
}
free(iterator[count]);
count--;
if (count == size - 6)
{
size -= 5;
iterator = realloc(iterator, size);
if (iterator == NULL)
{
/*fprintf(stderr, "Memory allocation did not succeed\n");*/
exit(1);
}
printf("realloced to smaller\n");
}
}
}
正如在malloc
中一样,您需要以字节为单位指定大小。例如:
v = realloc(iterator, size * sizeof *iterator);
if( v != NULL ){
iterator = v;
}
这是一个常见错误,可能是选择“尺寸”以外名称的一个很好的理由。 (也许称之为“能力”)。
请注意,尽管在您的代码中执行 iterator = realloc(iterator, size * sizeof *iterator)
是可以的,因为如果 realloc returns NULL,您会立即中止程序,但我修改了代码以使用不同的变量,只是为了向未来的读者强调该代码模式。