typedef struct {
char *word;
} STR;
int main()
{
STR *arr=(STR*)malloc(5*sizeof(*arr));
STR[2].word=(char*)malloc(200*sizeof(char));
STR[2].word=(char*)realloc(,400*sizeof(char));
return 0;
}
这不会起作用并且会写出许多错误。 如何在动态结构数组中动态分配数组?
答案 0 :(得分:1)
您的主要问题是,您在使用typedef
名称STR
时,在分配和重新分配arr
时应使用变量名称arr[2].word
。
NOT 强制转换malloc
,这是不必要的。有关详细说明,请参阅:Do I cast the result of malloc?。您需要分配5 STR
的数组:
STR *arr = malloc (5 * sizeof (*arr)); /* allocate array of 5 STR */
(注意:括号是sizeof
的可选项,因此也可以正确编写):
STR *arr = malloc (5 * sizeof *arr); /* allocate array of 5 STR */
宣布STR *arr = malloc (5 * sizeof (*arr))
后,您按如下方式分配word
:
arr[2].word = malloc (200 * sizeof *(arr[2].word));
不是的
STR[2].word = malloc (200 * sizeof *(arr[2].word));
您必须验证每个分配。 E.g:
STR *arr = malloc (5 * sizeof (*arr)); /* allocate array of 5 STR */
if (!arr) {
fprintf (stderr, "error: virtual memory exhausted.\n");
return 1; /* or handle error as appropriate */
}
从不realloc
使用指针本身,如果realloc
失败,您丢失了指向原始数据的指针,无法释放内存。而是使用一个简单的临时变量:
void *tmp = realloc (arr[2].word, 400 * sizeof *(arr[2].word));
if (!tmp) {
fprintf (stderr, "error: realloc() virtual memory exhausted.\n");
return 1;
}
arr[2].word = tmp;
在任何动态分配内存的代码中,对于分配的任何内存块,您都有2个职责:(1)始终保留指向起始地址的指针因此,(2)当不再需要时,它可以释放。养成跟踪和释放你分配的所有内存的习惯,而不是依赖退出来完成它。当您开始编写更复杂的代码以在代码中的函数内分配内存时,这将带来好处。在这种情况下,您需要:
free (arr[2].word); /* free allocated memory */
free (arr);
把这些碎片放在一起,你可以这样做:
typedef struct {
char *word;
} STR;
int main (void)
{
STR *arr = malloc (5 * sizeof (*arr)); /* allocate array of 5 STR */
if (!arr) { /* validate allocation */
fprintf (stderr, "error: virtual memory exhausted.\n");
return 1; /* or handle error as appropriate */
}
/* allocate/validate arr[2].word */
if (!(arr[2].word = malloc (200 * sizeof *(arr[2].word)))) {
fprintf (stderr, "error: virtual memory exhausted.\n");
return 1; /* or handle error as appropriate */
}
/* realloc/validate using temporary variable */
void *tmp = realloc (arr[2].word, 400 * sizeof *(arr[2].word));
if (!tmp) {
fprintf (stderr, "error: realloc() virtual memory exhausted.\n");
return 1;
}
arr[2].word = tmp;
free (arr[2].word); /* free allocated memory */
free (arr);
return 0;
}
示例使用/ Valgrind输出
您必须使用内存错误检查程序,以确保您没有在已分配的内存块之外/之外写入,尝试读取或基于未初始化的值跳转,最后确认您已拥有释放了你分配的所有内存。
对于Linux valgrind
是正常的选择。有许多微妙的方法可以滥用指针或新的内存块。使用内存错误检查器可以识别任何问题并验证您分配的内存的正确使用,而不是通过segfault
查找问题。每个平台都有类似的记忆检查器。它们都很简单易用,只需通过它运行程序即可。
例如,编译代码并将可执行文件保存为./bin/alloc
,然后只需在程序作为第一个参数的情况下运行valgrind
,就可以基本使用valgrind
:
$ valgrind ./bin/alloc
==8949== Memcheck, a memory error detector
==8949== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==8949== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==8949== Command: ./bin/alloc
==8949==
==8949==
==8949== HEAP SUMMARY:
==8949== in use at exit: 0 bytes in 0 blocks
==8949== total heap usage: 3 allocs, 3 frees, 640 bytes allocated
==8949==
==8949== All heap blocks were freed -- no leaks are possible
==8949==
==8949== For counts of detected and suppressed errors, rerun with: -v
==8949== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
始终确认释放所有堆块 - 不可能泄漏并且同样重要错误摘要:0个上下文中的0个错误。 (注意:某些操作系统没有提供足够的内存排除文件(排除系统和操作系统内存不被报告为正在使用的文件),这将导致valgrind
报告该文件尽管你完成了自己的工作并释放了你分配并控制的所有区块,但是有些记忆尚未被释放。)
仔细看看,如果您有任何问题,请告诉我。
(注意:C支持小写名称,为常量和宏保留全部大写。它只是风格,所以由你决定。)
答案 1 :(得分:0)
这似乎是多余的。但是,如果您尝试使用您的结构创建一个字符串数组,其中第三个元素作为199字符字符串malloc,然后重新分配为399字符字符串,您可以这样做:
STR *arr = (STR*)malloc(5*sizeof(STR));
arr[2].word = (char*)malloc(200*sizeof(char));
arr[2].word = (char*)realloc(arr[2].word,400*sizeof(char));
答案 2 :(得分:-1)
#include <stdio.h>
#include <stdlib.h>
typedef struct{
char *word;
}STR;
int main(){
STR *arr=(STR*)malloc(5*sizeof(STR));
arr[2].word=(char*)malloc(200*sizeof(char));
if(realloc(arr[2].word, 400*sizeof(char))==NULL){
/* increasing char array size from 200 to 400 failed. 200 char array was unchanged */
printf("increasing array size not OK\n");
}
else{
printf("increasing array size OK\n");
}
free(arr[2].word);
free(arr);
return 0;
}