无法分配指针 linux 接收的内存 [英] Failing to alloc memory received by a pointer linux

查看:47
本文介绍了无法分配指针 linux 接收的内存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a function that receives by a pointer the location where will be stored. This place can have different other similar structs.The function has to read a file. This file have stored a struct, which i need to read.

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 告诉我这个,

When I run the code I get SEGFAULT and valgrind tell me this,

主题 2:
==2746== 大小为 2 的无效读取
==2746== 在 0x80523B4:db_read_from_file (code.c:3069)
==2746== 由 0x20303333: ???
==2746== 地址 0x0 未被堆栈、malloc 或(最近)释放

Thread 2:
==2746== Invalid read of size 2
==2746== at 0x80523B4: db_read_from_file (code.c:3069)
==2746== by 0x20303333: ???
==2746== Address 0x0 is not stack'd, malloc'd or (recently) free'd

这是"DEBUG_PRINT("User id: %d",holder.user_manage[i].user_id);"所以显然看起来我没有把它存放在正确的地方.你能帮我吗?

This is the line of "DEBUG_PRINT("User id: %d",holder.user_manage[i].user_id );" So obviously looks like I am not storing it in the right place. Can u help me?

推荐答案

Priority Nr 1
在多看了你的代码之后,我怀疑你的转换和你做的一样多,因为你不断收到关于不兼容的 [指针] 类型" 等的编译器警告.这些警告的存在是有原因的:有一个问题,那里可能是错误的来源.不要隐瞒,不要忽视它:修复它!

Priority Nr 1
After looking at your code a bit more, I suspect you're casting as much as you do, because you kept getting compiler warnings about "incompatible [pointer] types" and the like. Those warnings exist for a reason: there's an issue, a possible source for bugs there. Don't hush it up, don't ignore it: FIX IT!

是的,有时需要进行这些转换,有时编译器会在您知道自己在做什么时抱怨您的代码.在这种情况下,您可以添加强制转换,但不要将这些强制转换视为编译器噱头:它们是告诉编译器您知道自己在做什么的方式.你刚刚疯狂地让编译器闭嘴.这很糟糕.

Yes, sometimes those casts are required, and sometimes compilers complain about your code when you know what you're doing. In that case, you can add a cast, but don't think of those casts as compiler-gags: they are ways to tell the compiler that you know what you're doing. You've just gone cast-crazy to get the compiler to shut up. That's bad.

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

Next
In both your db_read_from_file calls from main, you are passing pointer to a null pointer to your function. That means you still have to allocate memory to actually go and store that data, or you have to redefine holder to something like:

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

如果将它们作为指针保留,只需在 main 中分配 holder 的所有成员:

If you keep them as pointers, just allocate all members of holder in main:

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

最大的
正如某事已经提到的:

The big one
As sth already mentioned:

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

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

You are passing &prt, which reads: address of prt. This variable in itself is already a pointer, the memory address of a pointer is, again, a pointer. A pointer to a pointer (double indirection, avoid if possible...). Now as if that weren't enough: look at what you pass to your function:

db_read_from_file(&holder.user_manage);

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

Keep in mind that holder.user_manage already is a pointer, you are passing a pointer to a pointer! Thats double indirection. Then, you pass a pointer to this pointer to a pointer to memcpy!! Yes, you may have to read this last sentence again. But in short: you are passing a pointer, to a pointer, to a pointer to a struct, where that last bit (the pointer to a struct) could just be a null-pointer, too!

所以你所拥有的是:

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

将 memcpy 视为一个函数,基本上可以做到这一点:

Think about memcpy as a function that, basically does this:

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!

Notice that the destination is being dereferenced (*dest++). If you pass a pointer to a pointer(&prt), and dereference it, you end up with a pointer, right? That's what you are writing to => *(&prt) == prt!

演员表和你使用它的方式表明你相信你正在写入任何 prt 指向的东西,而实际上你试图将 90 个字节写入任何指向 prt 指向.它指向 prt,后者又指向一个指针.只有在第三个隐含之后,我们才能找到结构......这太疯狂了.
无论如何,指针的大小在 32 位系统上是 4 个字节,在 64 位系统上是 8 个字节.您正在复制 90 个字节,因此您可能最终会出现在不该弄乱的内存中.

The cast, and the way you use it suggest you believe you're writing to whatever prt is pointing to, while in fact you are trying to write 90 bytes to whatever the pointer to prt is pointing to. And it's pointing to prt, which in turn points to a pointer. Only after this third inderiction, we find the struct... that's just crazy.
Anyway, the size of a pointer is 4 bytes on a 32 bit system, 8 on 64 bits. You are copying 90 bytes, so you probably end up in memory you shouldn't mess with.

用这个替换你的代码:

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 指向的结构的某些内容(第二级)时,您必须取消引用它,以获得常规指针.比如分配内存:

And keep in mind that, whenever you want to change something of the struct that prt points to (2nd level), you have to dereference it, to get a regular pointer. For example, allocating memory:

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

必须变成:

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

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

However, this is still wrong in many ways. What you actually need, is realloc, because prt might already be pointing at allocated memory:

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

它更干净、更安全.

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

Also check if your function isn't being passed a null pointer, do away with needless casts (they're clutter), and always check the return value of functions!

这篇关于无法分配指针 linux 接收的内存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆