C - 动态字符串释放和动态数组

时间:2016-01-08 19:06:02

标签: c arrays string memory-management

我有一个与本学期编程项目有关的问题。 我有一个具有结构的动态数组,该结构包含字符串的参数。问题是我需要将该字符串从静态更改为动态。    我编写了函数,要求输入字符串并将其存储在动态数组中然后返回它。 在程序的后面,我需要将数组中的信息(存储动态字符串)写入二进制文件。 我怎样才能实现这一目标,如何知道何时以及如何正确释放该动态字符串的内存? 如果我释放存储字符串的数组,是否还要释放存储字符串本身的内存?

我的数组将存储字符串:

inspections *inspectionsArray;


char* dynamicString(){
    char *stringPointer = NULL,*paux = NULL, char;
    int stringSize = 1,stringEnd = 0,i;
    stringPointer = (char*)malloc(sizeof(char)); 
    if (stringPointer == NULL) {
        printf("\nError alocating memory");
    }else{
        printf("\nEnter String: ");
        while (char != EOF && char != '\n') {
            char = getc(stdin); //Obter o char do stding
            paux = realloc(stringPointer, stringSize*sizeof(char));
            if (paux != NULL) {
                stringPointer = paux;
                stringPointer[stringEnd] = char; //meter o char na string
                stringSize++; //incrementar o tamanho da string
                stringEnd++;
            }else{
                printf("\nErro a realocar memoria para a string");
            }
        }
        stringPointer[stringEnd] = '\0';
        printf("\nString: %s", stringPointer);
    }
    return stringPointer;
}

我将把我的字符串存储在其中的结构。

typedef struct
{
    //A bunch of parameters in here
    char *dynamicString;

} inspection;


enter code here

我用来将数据存储到数组的函数:

inspectionArray* registerInspection(inspection *inspectionArray){
    char *string;
    //I removed a bunch of code to not confuse things
    string = dynamicString;

    return inspection;
}

保存文件的功能:

void saveBinaryFile(inspection *inspections, int inspectionCounter)
{
    FILE * inspectionArrayFile;


    fileInspections = fopen("inspections.dat","wb"); 


    if (fileInspections == NULL)
    {
        perror("\nError opening the file");
    }
    else
    {
        fwrite(&inspectionCounter, sizeof (int), 1, inspectionArrayFile);
        fwrite(inspections, sizeof(tipoVeiculo), inspectionCounter, inspectionArrayFile);
        // I write a bunch of stuff and verify it properly
        fclose(inspectionArrayFile);

    }
}

如何正确阅读和释放字符串?

我试过了:

void freeArrayStrings(inspections *inspectionsArray,int counter){
    int i;
    for (i=0; i<counter; i++) {
        free(inspectionArray[i].dynamicString);
    }
}

3 个答案:

答案 0 :(得分:1)

您应该显示您的代码,以增加适当回答的机会。如果你要求释放存储指针到另一个内存的内存,请从malloc获取,如下例所示:

struct str_wrap
{
    char *str;
    int  strlen;
};

int main()
{
    struct str_wrap *sw = malloc(sizeof *sw);
    if (sw == NULL) return -1;

    sw->str = malloc(strlen);
    if (sw->str == NULL)
        // handle
    sw->strlen = strlen;
    // many things with sw...

然后是的,您必须拨打free两次(注意:您拨打malloc的次数相同):

    // free the memory
    free(sw->str);
    free(sw);
}

答案 1 :(得分:1)

除非你有一些特定的理由为dynamicString()函数使用面向字符的输入,否则你可以通过使用面向行的来大大简化你的生活。 em>标准C库提供的输入函数(例如fgetsgetline)。另外,在C语言中,您通常会避免使用 camelCase 名称,而是使用小写来表示所有变量和函数名称。

对于dynamicstring()功能,使用getline您的功能会缩减为:

char *dynamicstring (inspection *i)
{
    char *line = NULL;  /* buffer for input                 */
    size_t n = 0;       /* alloc size 0 - getline decides   */
    ssize_t len = 0;    /* no. of character read (or EOF)   */

    printf("\nEnter String: ");

    len = getline (&line, &n, stdin);   /* read input   */

    if (len <= 1) {  /* line contains only '\n', 0, EOF */
        free (line);
        return NULL;
    }

    while (len > 0 && line[len-1] == '\n') /* remove '\n'  */
        line[--len] = 0;

    i->dstring = line;    /* assign pointer to dstring  */

    return line;
}

注意:以上我对您的dstring会员使用char *dynamicString;

您可以通过获取最终getline的长度,将内存分配大小从line分配的默认值精简到仅为输入字符串所需的数量,并分配该内存量(+1对于 nul-terminator ),并将line复制到新的内存块。您可以使用strdup功能一次完成所有操作。例如,您可以将以下内容添加到上面的函数中,然后返回str

    char *str = NULL;   /* pointer for final string storage */
    ...
    str = strdup (line);  /* refine allocation size     */
    free (line);

    i->dstring = str;     /* assign pointer to dstring  */

    return str;

即使进行了改进,完成的功能也比原始功能简单得多。现在注意:无论你是否分配了返回,因为如果输入不为空,函数只返回一个分配,你的某些inspection字符串成员可能会有一些成员将被分配,一些空。因此,您需要在释放内存之前进行检查。 e.g:

    if (ia->dstring)
        free (ia->dstring);

与往常一样,在动态分配内存时,请使用内存错误检查程序(如Linux上的valgrind)来确认正确使用和释放您分配的内存。使用此输入函数的一个简短示例是:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    char *dstring;
} inspection;

char* dynamicstring (inspection *i);

int main (void) {

    inspection *ia= NULL;

    if (!(ia= malloc (sizeof *ia))) {
        fprintf (stderr, "error: virtual memory exhausted.\n");
        return 1;
    }

    if (dynamicstring (ia)) {
        printf ("\n inspectionArray->dynamicstring : %s\n\n", ia->dstring);
        if (ia->dstring)
            free (ia->dstring);
    }
    free (ia);

    return 0;
}

char *dynamicstring (inspection *i)
{
    char *str = NULL;   /* pointer for final string storage */
    char *line = NULL;  /* buffer for input                 */
    size_t n = 0;       /* alloc size 0 - getline decides   */
    ssize_t len = 0;    /* no. of character read (or EOF)   */

    printf("\nEnter String: ");

    len = getline (&line, &n, stdin);   /* read input   */

    if (len <= 1) {  /* line contains only '\n', 0, EOF */
        free (line);
        return NULL;
    }

    /* using shorthand 'len' instead of 'len > 0'
       both test false when 'len' is 0  */
    while (len && line[len-1] == '\n') /* remove '\n'  */
        line[--len] = 0;

    str = strdup (line);  /* refine allocation size     */
    free (line);

    i->dstring = str;     /* assign pointer to dstring  */

    return str;
}

尝试一下,如果您有疑问,请告诉我。

答案 2 :(得分:0)

  1. 您有错误:stringPointer = (char*)malloc(sizeof(char)); 你需要stringPointer = (char*)malloc(sizeof(char *)); sizeof(char)可能是1个字节; sizeof(char *)大概是4。 您可能会因为某些内存系统总是分配至少32个字节而侥幸成功...

  2. 不要对每个输入字符重新分配。相反,声明char buf [255]或其他一些最大大小,保留一个大小索引,将输入字符分配给结尾,然后最后执行stringPointer = malloc(isize + 1)和strcpy(stringPointer,buf);如果您确实需要一个巨大的输入缓冲区,请从4K或1M开始,然后在填充该空间时重新分配。