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

时间:2014-06-19 13:49:02

标签: c pointers struct calloc

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

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不是堆栈&#39; d,malloc&d; d或(最近)免费&#39;

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

2 个答案:

答案 0 :(得分:2)

优先级Nr 1
在仔细查看你的代码后,我怀疑你和你一样多投射,因为你不断收到有关&#34;不兼容[指针]类型&#34; 的编译器警告类似。这些警告存在的原因是:存在问题,可能是存在错误的来源。不要慌起来,不要忽视它:修复它!

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

下一步
db_read_from_file来自main的{​​{1}}调用中,您将指向指向函数的空指针。这意味着您仍然必须分配内存以实际存储并存储该数据,或者您必须将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),并取消引用它,你最终得到一个指针,对吧?这就是你要写的东西=&gt; *(&prt) == prt

演员阵容以及你使用它的方式表明你相信你正在写任何prt所指向的内容,而实际上你正在尝试将90个字节写入任何指针{{1指向。并且它指向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

它更干净,更安全。

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

答案 1 :(得分:0)

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

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 holder;

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;
}

}

的main(){

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

}

我不确定我是否正在检查null prt,但剩下的工作正常。 我做了一些小改动,以完美的#34;只是缺少的东西是发送文件名作为函数的输入。看起来互斥锁正在100%肯定。