无法分配指针linux接收的内存

我有一个函数,通过指针接收将存储的位置。 这个地方可以有不同的其他类似结构。该函数必须读取一个文件。 这个文件存储了一个我需要阅读的结构。

typedef struct user_manage_t{ short int user_id; char permission; long int other_id; long int check; }user_manage_t; typedef struct holder_t{ user_manage_t *user_manage; user_manage_t *user_manage_backup; //(...)and a lot of stuff }holder_t; holder_t holder; int db_read_from_file(user_manage_t *prt){ DEBUG_PRINT("READ_FROM file started"); FILE *fd_read; char buffer[480]; int read, bytesRead=0; int num; const struct user_manage_t *header; fd_read = fopen("/home/user/user_list","r+b"); if (fd_read == NULL) { printf("Error"); } else { DEBUG_PRINT("Its open!!!"); } do { read=fread(buffer, 2, 90, fd_read); bytesRead=bytesRead+read; DEBUG_PRINT("Number of bytes lidos read=%d",bytesRead); }while(read!=0); //(bytesRead < 480); header = (struct user_manage_t *) (buffer); fclose(fd_read); if ( NULL == ( prt = calloc( 10, sizeof(user_manage_t))))//aloca { DEBUG_PRINT("MAJOR_ERROR: couldnt allocate mem to users"); return -1; } else { memcpy( (struct user_manage_t *) &prt, &buffer, 90); DEBUG_PRINT("Users copied to main list"); for ( short int i=0;i<4 ; i++ ) { DEBUG_PRINT("i= %hd",i); DEBUG_PRINT("User id: %d",holder.user_manage[i].user_id ); DEBUG_PRINT("Permission: %d",holder.user_manage[i].permission); DEBUG_PRINT("other_ID:%ld",holder.user_manage[i].other_id); DEBUG_PRINT("Check_value:%ld", holder.user_manage[i].check); } return 1; } } main(){ db_read_from_file((struct user_manage_t *) &holer.user_manage); db_read_from_file((struct user_manage_t *) &holder.user_manage_backup); } 

当我运行代码时,我得到了SEGFAULT,valgrind告诉我这个,

线程2:
== 2746 ==读取大小2无效
== 2746 ==在0x80523B4:db_read_from_file(code.c:3069)
== 2746 == by 0x20303333:???
== 2746 ==地址0x0没有堆叠,malloc’d或(最近)免费

这是“DEBUG_PRINT(”用户ID:%d“,holder.user_manage [i] .user_id);” 所以看起来我好像不是把它存放在正确的地方。 你能帮我吗?

优先级Nr 1
在看了你的代码之后,我怀疑你和你一样投射,因为你不断得到关于“不兼容的[指针]类型”等的编译器警告。 这些警告存在的原因是:存在问题,可能存在错误来源。 不要嘘声,不要忽视它: 修复它!

是的,有时这些演员阵容是必需的,有时编译器会在你知道你在做什么时抱怨你的代码。 在这种情况下,您可以添加一个强制转换,但不要将这些强制转换视为编译器 – gags:它们是告诉编译器您知道自己在做什么的方法。 你刚刚疯狂地让编译器闭嘴。 那很糟。

下一个
maindb_read_from_file调用中,您将指针传递给指向函数的空指针。 这意味着您仍然必须分配内存来实际存储存储该数据,或者您必须将holder重新定义为:

 struct { user_manage_t user_manage;//not pointers, actual structs user_manage_t user_manage_backup; } holder; 

如果你把它们作为指针,只需在main中分配holder所有成员:

 holder.user_manage = malloc(sizeof *holder.user_manage);//and so on //preferably, though: if (NULL == (holder.user_manage_backup = malloc(sizeof *holder.user_manage_backup)) exit (EXIT_FAILURE);//error 

大的那个
如上所述:

 memcpy( (struct user_manage_t *) &prt, &buffer, 90); 

你正在传递&prt ,其中包括: prt地址。 这个变量本身已经是一个指针,指针的内存地址也是一个指针。 指向指针的指针(双重间接,尽可能避免……)。 现在好像这还不够:看看你传递给你的函数:

 db_read_from_file(&holder.user_manage); 

请记住, holder.user_manage已经是一个指针,您正在向指针传递指针! 这是双重间接。 然后,您将指向此指针的指针传递给指向memcpy的指针!! 是的,你可能需要再读一遍这句话。 但简而言之:您正在将指针传递给指针,指向结构的指针,其中最后一位(指向结构的指针)也可能只是一个空指针!

所以你有这个:

 memcpy(void ***, char *, 90);//where the prt is void ***, and **prt could be NULL 

把memcpy想象成一个函数,基本上这样做:

 void * memcpy( void *target, const void *src, size_t nr_of_bytes) { char *dest = target; char *from = src;//use char, as it is guaranteed to be 1 byte in size int i; while(nr_of_bytes--) *dest++ = *from++;//copy byte to destination, move pointer 1 byte return dest;//return destination } 

请注意,目标正在解除引用( *dest++ )。 如果你将一个指针传递给一个指针( &prt ),并取消引用它,你最终会得到一个指针,对吧? 这就是你写的=> *(&prt) == prt

演员表以及你使用它的方式表明你相信你正在写入任何prt所指向的内容,而实际上你正在尝试向prt指向的指针写入90个字节。 它指向prt ,而prt又指向指针。 只有在第三次入侵之后,我们才发现结构……这只是疯了。
无论如何,指针的大小在32位系统上是4个字节,在64位上是8个字节。 你正在复制90个字节,所以你可能最终在内存中你不应该搞乱。

用以下代码替换您的代码:

 memcpy(*prt, buffer, sizeof *prt);//copy max the sizeof whatever prt is pointing to 

并将db_read_from_file函数更改为:

 int db_read_from_file(user_manage_t **prt)//pointer to pointer! 

请记住,每当你想要改变某些prt指向的结构(第二级)时,你必须取消引用它,以获得一个常规指针。 例如,分配内存:

 if ( NULL == ( prt = calloc( 10, sizeof(user_manage_t))))//aloca 

必须成为:

 if ( NULL == ( *prt = calloc( 10, sizeof(user_manage_t))))//aloca 

但是,这在许多方面仍然是错误的。 你真正需要的是realloc ,因为prt可能已经指向已分配的内存:

 *prt = realloc(*prt, 10*sizeof **prt); if (*prt == NULL) //ERROR 

它更干净,更安全。

还要检查你的函数是否没有被传递空指针,消除不必要的强制转换(它们是混乱的),并且总是检查函数的返回值!

这是最终的代码,以防有些人遇到类似的情况:

 typedef struct user_manage_t{ short int user_id; char permission; long int other_id; long int check; 

} user_manage_t;

typedef struct holder_t {

 user_manage_t *user_manage; user_manage_t *user_manage_backup; pthread_mutex_t check_mutex; pthread_mutex_t backup_mutex; //(...)and a lot of stuff 

} holder_t;

holder_t持有人;

int db_read_from_file(user_manage_t ** prt,pthread_mutex_t mtx){

 DEBUG_PRINT("READ_FROM file started"); FILE *fd_read; char buffer[480]; int read, bytesRead=0; int num; const struct user_manage_t *header; fd_read = fopen("/home/user/user_list","r+b"); if (fd_read == NULL) { printf("Error"); } else { DEBUG_PRINT("Its open!!!"); } do { read=fread(buffer, 1, 480, fd_read); bytesRead=bytesRead+read; DEBUG_PRINT("Number of bytes lidos read=%d",read); }while(read!=0); //(bytesRead < 480); header = (struct user_manage_t *) (buffer); fclose(fd_read); if ( NULL != prt ) { status = pthread_mutex_trylock (&mtx); if (status != 0)//compor isto { DEBUG_PRINT("ERROR with lock"); return -1; } else { num = bytesRead / sizeof(user_manage_t); DEBUG_PRINT("prt is not null and num=%d",num); //should add an if to check if num >0 //if ( NULL == ( *prt = calloc( num, sizeof(user_manage_t))))//aloca if ( NULL == ( *prt = malloc(bytesRead))) { DEBUG_PRINT("MAJOR_ERROR: couldnt allocate mem to users"); status = pthread_mutex_unlock(&mtx); return -1; } else { //memcpy( *prt, header, sizeof(**prt)); memcpy( *prt, header, bytesRead); DEBUG_PRINT("Users copied to main list"); status = pthread_mutex_unlock(&mtx); for ( short int i=0;i<4 ; i++ ) { DEBUG_PRINT("i= %hd",i); DEBUG_PRINT("User id: %d",holder.user_manage[i].user_id ); DEBUG_PRINT("Permission: %d",holder.user_manage[i].permission); DEBUG_PRINT("other_ID:%ld",holder.user_manage[i].other_id); DEBUG_PRINT("Check_value:%ld", holder.user_manage[i].check); } return 1; } } } if ( NULL == prt ) { DEBUG_PRINT("Pointer is null!"); return 0; } 

}

主要(){

  db_read_from_file(&holer.user_manage, holder.check_mutex); db_read_from_file(&holder.user_manage_backup, holder.backup_mutex); 

}

我不确定我是否正在检查null prt,但其余的工作正常。 我做了一个小改动是“完美”只是缺少的东西是发送文件名作为函数的输入。它看起来像互斥锁100%肯定工作。