结构体动态数组中的malloc动态数组 [英] malloc dynamic array in dynamic array of structs

查看:139
本文介绍了结构体动态数组中的malloc动态数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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;
}

这将不起作用,并会写很多错误. 如何在动态结构数组中动态分配数组?

This won't work and write many errors. How can I dynamically allocate an array in a dynamic array of structs?

推荐答案

您的主要问题是您使用的是typedef名称STR,在分配和重新分配arr[2].word时应该使用变量名称arr

Your primary problem is you are using the typedef name STR where you should be using the variable name arr when allocating and reallocating arr[2].word.

不要强制返回malloc的返回值,这是不必要的.请参阅: 我是否强制转换malloc的结果? 以获取详细说明.您需要分配5个STR数组的所有操作是:

Do NOT cast the return of malloc, it is unnecessary. See: Do I cast the result of malloc? for thorough explanation. All you need to allocate an array of 5 STR is:

STR *arr = malloc (5 * sizeof (*arr));  /* allocate array of 5 STR */

(注意:括号对于sizeof是可选的,因此也可以正确编写):

(note: the parenthesis are optional with sizeof, so it could also be properly written):

STR *arr = malloc (5 * sizeof *arr);    /* allocate array of 5 STR */

声明STR *arr = malloc (5 * sizeof (*arr))后,按以下方式分配word:

After you declare STR *arr = malloc (5 * sizeof (*arr)), you allocate word as follows:

arr[2].word = malloc (200 * sizeof *(arr[2].word));

STR[2].word = malloc (200 * sizeof *(arr[2].word));

您必须验证每个分配.例如:

You must validate every allocation. 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失败,则您将丢失指向原始数据的指针,并且无法释放内存.而是使用一个简单的临时变量:

Never realloc using the pointer itself, if realloc fails, you have lost the pointer to your original data and cannot free the memory. Instead use a simple 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;

在您的任何动态分配内存的代码中,您对分配的任何内存块都有2个职责:(1)始终保留指向起始地址的指针因此,(2)当不再需要它时,可以释放.养成跟踪和释放分配的所有内存的习惯,而不是依靠退出来完成它.当您开始编写更复杂的代码以在代码中的函数内分配内存时,这将带来很多好处.在这种情况下,您将需要:

In any code your write that dynamically allocates memory, you have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed. Get in the habit of tracking and freeing all memory you allocate rather than relying on it being done by exit. This will pay dividends when you begin writing more complex code that allocates memory within functions in your code. In this case, you would need:

free (arr[2].word); /* free allocated memory */
free (arr);

将这些片段放在一起,您可以:

Putting those pieces together, you could do:

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输出示例

必须使用一个内存错误检查程序来确保您没有在所分配的内存块之外/之外进行写操作,试图读取或基于未初始化的值进行跳转,最后确认您已释放了所有内存您分配的内存.

It is imperative that you use a memory error checking program to insure you haven't written beyond/outside your allocated block of memory, attempted to read or base a jump on an uninitialized value and finally to confirm that you have freed all the memory you have allocated.

对于Linux valgrind是正常选择.有许多巧妙的方法可以滥用指针或新的内存块.使用内存错误检查器可以识别任何问题并验证分配的内存的正确使用,而不是通过segfault查找存在的问题.每个平台都有类似的内存检查器.它们都很容易使用,只需通过它运行程序即可.

For Linux valgrind is the normal choice. There are many subtle ways to misuse a pointer or new block of memory. Using a memory error checker allows you to identify any problems and validate proper use of of the memory you allocate rather than finding a problem exists through a segfault. There are similar memory checkers for every platform. They are all simple to use, just run your program through it.

例如,编译代码并将可执行文件另存为./bin/alloc,然后只需将程序作为第一个参数运行valgrind,即可基本使用valgrind:

For example, compiling your code and saving the executable as ./bin/alloc, you would then make basic use of valgrind simply by running valgrind with your program as the first argument:

$ 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报告尚未使用某些内存尽管您已经完成工作并释放了分配的所有块并在您的控制下,但仍然释放了.)

Always confirm All heap blocks were freed -- no leaks are possible and equally important ERROR SUMMARY: 0 errors from 0 contexts. (note: some OS's do not provide adequate memory exclusion files (the file that excludes system and OS memory from being reported as in use) which will cause valgrind to report that some memory has not yet been freed despite the fact you have done your job and freed all blocks you allocated and under your control.)

仔细看看,如果您有任何疑问,请告诉我.

Look it over and let me know if you have any questions.

(注意:C倾向于小写名称,保留常量和宏的全大写字母.这只是样式,所以由您自己决定.)

(note: C favors lower-case names, reserving all-caps for constants and macros. It's just style, so it is up to you.)

这篇关于结构体动态数组中的malloc动态数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆