【问题标题】:corrupted double-linked list after use fclose();使用 fclose() 后损坏的双链表;
【发布时间】:2016-01-01 17:56:11
【问题描述】:

我的程序有问题。 使用函数fclose() 后出现错误:

"* `./server' 中的错误:损坏的双链表:0x000000000251a230 * Przerwane (zrzut pamięci)"

如果我删除fclose() 函数everythink 就可以了。 这是我的功能代码:

FILE *fHandler;
struct udp_message **returnArray;
struct udp_message *message;
char *line = NULL;
uint32_t linesNum;
uint32_t i = 0;
size_t length; 
ssize_t read;

fHandler = fopen(filePath, "r");
if (fHandler == NULL) {
    perror("ERROR");
    return NULL;
}

returnArray = malloc(sizeof(struct udp_message *)*CONSOLE_BUFFER);
message = malloc(sizeof(struct udp_message));

while ((read = getline(&line, &length, fHandler)) != -1) {
    message = (struct udp_message *)line;
    if (message->messageTime < aboveTime) {
        continue;
    }

    returnArray[i] = malloc(sizeof(struct udp_message));
    memcpy(returnArray[i++], message, sizeof(struct udp_message));
}

memcpy(messageNum, &i, sizeof(i));
fclose(fHandler);

return returnArray;

【问题讨论】:

    标签: c fclose ansi-c


    【解决方案1】:

    查看这部分代码-

    message = malloc(sizeof(struct udp_message));       /* <--- 1 */
    
    while ((read = getline(&line, &length, fHandler)) != -1) {
       message = (struct udp_message *)line;            /*  <--- 2.  */
       if (message->messageTime < aboveTime) {
           continue;
       }
    

    您将内存分配给message(参见1.),但随后在while 循环中将其指向line2.)。

    所以你失去了对先前分配的内存的引用(这两个指针都指向同一个内存位置),因此如果你 free 他们,它将free 相同的内存导致双重 free 相同的内存位置。

    所以,如果你想让message 指向line,那么不要给message 分配内存。

    【讨论】:

    • @DanielHornik 欢迎 :-)
    • 你说的有道理,但是用getline读取udp消息仍然和其余代码不一致,循环不测试i是否变得太大。很可能代码并没有真正工作,它只是不再崩溃了。
    • @chqrlie 这是真的,因为我们不知道CONSOLE_BUFFER 的值,因此如果不检查i 可能会导致越界访问导致未定义的行为。
    【解决方案2】:

    可能值得检查对象不为空

    if(fHandler != NULL)
        fclose(fHandler);
    

    【讨论】:

      【解决方案3】:

      您不太可能使用getline 读取二进制 UDP 消息。 while 循环有可能迭代超过 CONSOLE_BUFFER 次,并且您在 returnArray 的末尾写入,从而破坏堆内部结构。 fclose() 释放与流关联的缓冲区,free 由于堆损坏而崩溃。

      顺便说一句,memcpy(messageNum, &amp;i, sizeof(i)); 可能不正确。您没有发布函数原型,但是您应该将returnArray 中存储的消息数量设置为*messageNum = i;,尤其是如果类型不是uint32_t *

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-09-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-01-01
        相关资源
        最近更新 更多