已释放对象的校验和不正确 - 对象在被释放后可能已被修改。我该如何解决?

Posted

技术标签:

【中文标题】已释放对象的校验和不正确 - 对象在被释放后可能已被修改。我该如何解决?【英文标题】:incorrect checksum for freed object - object was probably modified after being freed. how can I fix it? 【发布时间】:2019-05-31 17:02:37 【问题描述】:

运行代码时出现错误:ds(57203,0x70000fba3000) malloc: * 对象 0x7ff875402848 错误:已释放对象的校验和不正确 - 对象在被释放后可能已被修改。 * 在 malloc_error_break 中设置断点进行调试

有时它可以工作,有时它在尝试 malloc 新节点后崩溃(请参阅 createNode 函数),所以我怀疑错误来自那里。

我做错了什么?我该如何解决?

我已尝试调试代码并更改了几个 malloc,但无法解决问题。

正如我之前所说,我怀疑错误出在 createNode 函数中。

    #include <pthread.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>
    #include <unistd.h>
    #include <dirent.h>
    #include <string.h>


void* threadFunction(void* searchTerm);
void scanDirName(char * path, char * searchTerm);
char* rootSD;
pthread_mutex_t qlock;

struct Node 
    char* data;
    struct Node* next;
;

// Two glboal variables to store address of front and rear nodes.
    struct Node* front = NULL;
    struct Node* rear = NULL;

// To Enqueue an integer
void Enqueue(char* x) 
    pthread_mutex_lock(&qlock);
/*    printf("\nhere\n");*/
    struct Node* temp = (struct Node*)malloc(sizeof(struct Node));
    temp->data =x;
    temp->next = NULL;
    if(front == NULL && rear == NULL)
        front = rear = temp;
        pthread_mutex_unlock(&qlock);
        return;
    
    rear->next = temp;
    rear = temp;
    pthread_mutex_unlock(&qlock);


// To Dequeue an integer.
char* Dequeue() 
    pthread_mutex_lock(&qlock);
    struct Node* temp = front;
    if(front == NULL) 
        pthread_mutex_unlock(&qlock);
        return NULL;
    
    char* data;
    data = front->data;
    if(front == rear) 
        front = rear = NULL;

    
    else 
        front = front->next;
    

    free(temp);
    pthread_mutex_unlock(&qlock);
    return data;



void Print() 
    struct Node* temp = front;
    while(temp != NULL) 
        printf("%s ",temp->data);
        temp = temp->next;
    
    printf("\n");


void* threadFunction(void* st)

    char* filepath;
    filepath = NULL;
    char* searchTerm;
    searchTerm = (char*)st;

    while (filepath == NULL) 
        filepath = Dequeue();
    

    printf("about to enter with %s, %s\n",filepath, searchTerm);
    fflush(stdout);
    scanDirName(filepath, searchTerm);
    if (strcmp(filepath,rootSD) != 0)
        free(filepath);
    return (void*)1;




void scanDirName(char * path, char * searchTerm)
    DIR * d = opendir(path); // open the path
    char* str3;

    if(d==NULL) return; // if was not able return

;

    struct dirent * dir; // for the directory entries
    while ((dir = readdir(d)) != NULL) // if we were able to read somehting from the directory
    

        if(dir-> d_type == DT_DIR) //
            if (dir->d_type == DT_DIR && strcmp(dir->d_name, ".") != 0 & strcmp(dir->d_name, "..") != 0) // if it is a directory
            
                str3 = malloc(1+strlen("/") + strlen(searchTerm)+ strlen(dir->d_name) );
                if (!str3)
                    return;
                

                strcpy(str3, path);
                strcat(str3, "/");
                strcat(str3, dir->d_name);
                printf("\n---\n%s\n---\n",str3);
                Enqueue(str3);
                printf("Succ");
            
         else if(dir-> d_type == DT_REG) //
            if(strstr(dir->d_name, searchTerm))

                printf("%s/%s\n", path, dir->d_name);
            
        

    
    closedir(d); // finally close the directory


int main(int argc, char* argv[])


    if (argc != 4)
        printf("ERROR\n");
        exit(1);
    
    char* rootSearchDir = argv[1];
    char* searchTerm = argv[2];
    int threadsNumber = atoi(argv[3]);

    pthread_t threadsCollection[threadsNumber];

    rootSD = rootSearchDir;
    Enqueue(rootSearchDir);

    int i;
    for (i=0; i<threadsNumber; i++)
        if(pthread_create(&threadsCollection[i], NULL, threadFunction, (void*)searchTerm)) 

            fprintf(stderr, "Error creating thread\n");
            return 1;

        
    

    int rc;

    for (i=0; i<threadsNumber; i++)
        rc = pthread_join((threadsCollection[i]), NULL);
        if(rc) 
            fprintf(stderr, "Error joining thread, %d\n", rc);
            return 1;

        
    






此代码使用线程从根搜索目录开始搜索名称包含 searchTerm 的文件。

【问题讨论】:

注意:在isEmpty中:检查if (pQueue == NULL)应该返回true,好像没有队列,那么至少它是空的。 当队列中只有一项时检查Dequeue 操作。注意Enqueue中,当队列为空时,设置pQueue-&gt;head = pQueue-&gt;tail = item; 在创建节点时你永远不会初始化指针 prev,因此它们的内容是不确定的,如果你取消引用它们,你会得到未定义的行为。可能不会导致这种情况,但仍然是一个问题。 错误是我之前的评论:item is not dequeued. 维护size 不是正确的方法:当头尾为空时队列为空。保持大小容易出错。 【参考方案1】:

问题是您分配searchTerm 的大小但复制path

path 的长度和searchTerm 的长度相同的可能性较小。从而越界访问str3 并调用未定义的行为。

         str3 = malloc(1+strlen("/") + strlen(searchTerm)+ strlen(dir->d_name) );
            if (!str3)
                return;
            

            strcpy(str3, path);  //Here
            strcat(str3, "/");
            strcat(str3, dir->d_name);

解决分配长度为path的内存。

str3 = malloc(1+strlen("/") + strlen(path)+ strlen(dir->d_name) );

【讨论】:

以上是关于已释放对象的校验和不正确 - 对象在被释放后可能已被修改。我该如何解决?的主要内容,如果未能解决你的问题,请参考以下文章

释放对象的校验和不正确

释放对象的校验和不正确 - 分配问题

realloc 错误:释放对象的校验和不正确

CGContextDrawImage(Swift)上的间歇性“释放对象的校验和不正确”错误

当矩阵维数不是4的倍数时,如何避免AVX2的错误?

对象可能在被释放后被修改