从预分配内存中直接读取 C 中的结构失败

Doing a direct struct read in C from preallocated memory failed

我假设它又是一个指针问题,但我想在这里做的是有一个函数搜索内存来查看 IP 地址是否存在,如果不存在则随机内存 space 为 IP 地址保留,返回零。该函数将 IP 地址作为字符串作为第一个参数,第二个参数指向结构。当执行 main() 函数时,result 应该等于 0,result2 应该等于 1,但是我却崩溃了,我认为这与我分配指针的方式有关?

在这个片段中...

ip=(iprec*)p;

我正在尝试设置传递给函数的 iprec 结构(之前由 malloc 分配),但我不确定在该语句的何处添加或删除星号。

这是代码的其余部分。

char *shma;

typedef struct{
    unsigned char u;
    unsigned char a[4];
    unsigned int otherdata;
} iprec;

static int loadip(char* remoteip,iprec *ip){
    char *p=shma;
    int v=0;
    char *ep;
    unsigned char a[4];
    sscanf(remoteip,"%d.%d.%d.%d",a[0],a[1],a[2],a[3]);
    int i,n;int sz=5000;
    int szr=sizeof(iprec);
    for (i=3;i<sz;i+=szr){
        ip=(iprec*)p;
        if (ip->u=='Y'){
            for (n=0;n<=4;n++){
                if (a[n]!=ip->a[n]){break;}
            }
            if (n >= 3){v=1;break;}
        }else{
            ep=p;
        }
        p+=szr;
    }
    if (v==0){
        ip=(iprec*)ep;
        for (n=0;n<=3;n++){
            ip->a[n]=a[n];
        }
    }
    return v;
}

int main(){
    char *shma=(char*)malloc(5000); //alloc 5000 bytes for example.
    iprec *x=(iprec*)malloc(sizeof(iprec));
    int result=loadip("127.0.0.1",x);
    int result2=loadip("127.0.0.1",x);
}
  1. 替换

    sscanf(remoteip,"%d.%d.%d.%d",a[0],a[1],a[2],a[3]);

sscanf(remoteip,"%d.%d.%d.%d",&a[0],&a[1],&a[2],&a[3]);

sccanf 需要指针类型参数。

  1. shma 应该是全局的。

我还没有对你的代码进行完整的分析,但这是你崩溃的根源。最下面是分辨率

分析

在您的代码段顶部,您有

char *shma;

这是一个名为 shma 的文件范围(全局)对象,具有静态持续时间存储。它在 main() 执行之前被初始化为 0。

然后,在主要部分,您有:

int main(){
    char *shma=(char*)malloc(5000); //alloc 5000 bytes for example.

在这里声明一个名为 shma 的新对象。它具有块作用域(仅存在于 main 的上下文中),具有自动存储功能。你从 malloc() 给它分配一个指针。然后你调用 loadip.

loadip

char *p=shma;

它声明了一个名为 p 的新对象,具有块范围(存在于 loadip 中)和自动存储。您将其设置为 shma注意 这是分配全局 shma,而不是 main 中的那个,因为 main 中的那个只存在于 main 中,而 loadip 在 main 之外。全局 shma 是 0,所以现在 p 也是 0(至少对于你的第一个循环)。

然后,你做:

    ip=(iprec*)p;

所以,因为 p 是 0,所以现在 ip 是 0。在下一行:

    if (ip->u=='Y'){

您正在取消引用 ip 以获取成员 u。在大多数系统上,这种取消引用将导致分段错误(或类似的内存访问冲突),因为您实际上已经取消引用了 NULL(0 地址)。

修复此问题

改变

int main(){
    char *shma=(char*)malloc(5000); //alloc 5000 bytes for example.

进入

int main(){
    shma=(char*)malloc(5000); //alloc 5000 bytes for example.

这将导致 main 分配给全局 shma 而不是创建新的本地。

自从我完成 C 后有一段时间了,但有一些想法:

char *p=shma;

但 shma 尚未初始化 - 因此 "ip=(iprec*)p;" 意味着 ip 将不是有效值。

unsigned char a[4];
sscanf(remoteip,"%d.%d.%d.%d",a[0],a[1],a[2],a[3]);

您需要接收变量的地址(即 &a[0]、&a[1]、...)。 此外,由于 '%d' 将写入 4 字节整数(scanf 不知道它是一个 char 数组),最好使用 "int a[4]"

ip=(iprec*)p;

但是 ip 是一个输入参数 - 所以在这里您要覆盖(即丢弃)用户在第二个参数中提供的任何值。

if (v==0){
    ip=(iprec*)ep;

即使 v=0,ep 仍然有可能没有被初始化(eg.if 所有 ip->u == 'Y' 但 a 数组在第一个或第二个不同值)