malloc的额外记忆力难吗?

时间:2011-03-09 04:30:33

标签: c memory-management malloc

我有这个指向最初由malloc分配的结构的“数组”指针,我需要在初始容量变满时通过增量添加额外的内存。当我尝试分配更多内存时,第一个元素似乎消失并导致程序崩溃。有人可以帮忙吗?

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

int idCompare ( const void * a, const void * b ){
    message *m1 = *(message **)a;
    message *m2 = *(message **)b;
    return m1->messageId - m2->messageId;     
}

int textCompare( const void *a, const void *b ) {
    message *m1 = *(message **)a;
    message *m2 = *(message **)b;
    return strcmp(m1->messageText, m2->messageText);
}

int main(void)
{   
    int id, i;
    int count = 0;

    char cmd[MAX_CMD_LEN];
    char msg_text[MAX_TEXT_LEN];
    message **mList = malloc(INITIAL_CAPACITY * sizeof(message));
    int capacity = INITIAL_CAPACITY * sizeof(message);
    int size = 0;

    while (scanf("%s", cmd)){

        if (!strcmp(cmd, "add")){
            printf("(pre) Capacity =%d, Count =%d, Size =%d\n", capacity, count, size);
            int found = 0;
            scanf("%d\n", &id);
            fgets(msg_text, sizeof(msg_text), stdin);

            if(size >= capacity){
                capacity = size;
                *(mList + count) = malloc(CAPACITY_INCREMENT * sizeof(message));
                message *p = *(mList + count);                    
                if(p == NULL){                                          //If malloc fails, free mList and exit.
                    printf("out of memory\n");
                    free(*mList);
                    exit(1);
                }
            }   

            for(i = 0; i < count; i++){                                 //If existing id is found, send flag & do not add.
                message *p = *(mList + i);
                if(p->messageId == id){  found = 1;  }
            }

            if(!found){                                                
                message *p = *(mList + count);          
                p->messageId = id;
                p->messageText = malloc(strlen(msg_text)+1);    
                strcpy(p->messageText, msg_text);           
                count++;      
                size += 10 * sizeof(message);
                printf("(post) Capacity =%d, Count =%d, Size =%d\n", capacity, count, size);
            }
        }

        else if (!strcmp(cmd, "delete")){                       //Cycle through mList, if id is found, shift elements left.
        scanf("%d", &id);
        for(i = 0; i < count; i++){                
            message *p = *(mList + i);
                if(p->messageId == id){  
                    for(;i < count; i++){*(mList + i) = *(mList + i + 1);}
                    count--;
                    size -= 10 * sizeof(message); 
                }
            }  
        }

        else if (!strcmp(cmd, "find")){                                 //Cycle through mList, if id is matched, print to stdout.
        scanf("%d", &id);
        for(i = 0; i < count; i++){              
            message *p = *(mList + i);
                if(p->messageId == id){  printf("%s", p->messageText);  }
            } 
        }

        else if (!strcmp(cmd, "output")){                       //Cycle through mList, print all to stdout.
        for(i = 0; i < count; i++){
            message *p = *(mList + i);
                printf("%s", p->messageText);
            }
        }

        else if (!strcmp(cmd, "sortById")){  qsort (mList, count, sizeof(message*), idCompare);  }

        else if (!strcmp(cmd, "sortByText")){  qsort (mList, count, sizeof(message*), textCompare);  }

    }
    return 0;
}

3 个答案:

答案 0 :(得分:4)

首先,您的消息列表包含

message **mList

但是你没有将它用作指向指针列表的指针。你永远不会在列表中分配指针!

例如,这将是“正确的”(尽管效率低下):

message **mList = malloc(INITIAL_CAPACITY * sizeof(message*));
for (i = 0; i < INITIAL; i++) {
   mList[i] = malloc(sizeof(message));
}

现在您拥有了自己表达的数据结构。

但是,你也可以执行:

message *mList = malloc(INITIAL_CAPACITY * sizeof(message));

在所有情况下,一旦解决了内存访问问题,就可以使用realloc()调整其大小。

答案 1 :(得分:0)

您需要使用realloc()来分配更大的内存块。

realloc()将分配一个新块(如果需要),将原始数据复制到新块,并释放旧块(如果需要)。

如果您再次调用malloc(),则会为新内存块分配新值。这也意味着你已经创建了内存泄漏,因为你的原始内存块没有被释放。

答案 2 :(得分:0)

至少从事物的外观来看,你错误地定义了mlist

message **mList = malloc(INITIAL_CAPACITY * sizeof(message));

由于您为message结构分配空间,看起来mList应该只是message *

message *mList = malloc(INITIAL_CAPACITY * sizeof(message));

或(我通常喜欢的):

message *mList = malloc(INITIAL_CAPACITY * sizeof(*mList));

总的来说,你的代码似乎让两个相当不同的案例混淆不清。一个是你动态分配一个message的数组,另一个是你正在分配一个指向消息的指针数组。虽然这个问题并不完全重复,但我之前发布了answer图表,以图形方式显示差异。

虽然其他答案是正确的,realloc通常对扩展分配很有用,但我认为你需要多考虑一下你正在扩展的内容:message的数组,或指针数组,每个实际message分别分配。从事物的外观来看,message结构本身包含一个指向消息实际文本的指针,它与message结构本身分开分配。在这种情况下,可能更有意义地分配消息对象数组而不是指针数组。