程序问答   发布时间:2022-06-01  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了递增指针是否发生在 C大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决递增指针是否发生在 C?

开发过程中遇到递增指针是否发生在 C的问题如何解决?下面主要结合日常开发的经验,给出你关于递增指针是否发生在 C的解决方法建议,希望对你解决递增指针是否发生在 C有所启发或帮助;

我正在增加用于分配的指针变量,但它给了我段错误消息。程序没有任何问题,因为我的程序一直执行到最后,除了 return 语句。所以基本上我在想

当我们像 pointer+1 这样增加指针时,我们在连续内存和函数内部向前推进——可能在现实中——变量和函数调用的地址可能以分散的方式定位——如果我是,请纠正我错误的。当我们增加指针以移动到下一个连续的内存地址并且该内存可以是任何东西(其他一些函数/程序)并且我的分配是在某个区域上完成的,该区域为其他东西提供内存,并且可能是{{的内存区域之外的东西1}} 函数。这是我的代码

abc

有一个问题是为什么我在 #include <stdio.h> struct abc{ char *c;}; voID abc(struct abc **t1); int main() { struct abc *k; abc(&k); printf("%s\n",k->c); // printf("%s\n",k->c); printf("%s\n",(k+1)->c); // printf("%s\n",(k+2)->c); return 1; } voID abc(struct abc **t1){ *t1=(struct abc *)malloc(sizeof(struct abc )); (*t1)->c="Hello"; *(t1+1)=(struct abc *) malloc((sizeof(struct abc ))); (*t1+1)->c="cool"; *(t1+2)=(struct abc *) malloc((sizeof (struct abc ))); //(*t1+2)->c="Super cool"; } 函数返回时出现段错误。因为主内存区域不同于 @H_237_5@main 内存区域。我需要对此进行一些解释,问题是这种分配方式是错误的。如果它没有错,那么如何更正以使其在没有段错误的情况下工作

更新

abc

上面的代码在没有 segFault 的情况下工作,但它与答案不同,所以上面的代码有什么问题

如下也有效

    #include <stdio.h>

    struct abc{ char *c;};

    voID abc(struct abc **t1);
    voID abc2(struct abc *t1);
    int main() {
        struct abc *k;
        abc(&k);
        //printf("%s\n",k->c);
      // k->c="hi"; Seg Fault causes because ->c is immutable from assigning String literal
       // printf("%s\n",(k)->c);
        printf("%s\n",(k+1)->c);
        printf("%s\n",(k+2)->c);
    //   / printf("%s\n",(k+2)->c);

       return 1;
    }

    voID abc(struct abc **t1){


        *t1=(struct abc *)malloc(sizeof(struct abC)*3);
        abc2((*t1));
           abc2((*t1+1));
        abc2((*t1+2));
     
    }

    voID abc2(struct abc *t1){
        (t1)->c="cool";
    }

解决方法

您传递给 abc() 的值指向未初始化的内存。您必须为要存储的三个结构体留出 @H_237_5@malloc 空间。否则,取消引用它是未定义的行为。在我看来,您的目标是让 k 成为一个包含 3 个指向结构的指针的数组。如果是这种情况,您应该像这样声明:

struct abc **k = (struct abc **)malloc(sizeof(struct abc *) * 3);

这应该在 32 位系统上分配 12 个字节(每个指针 4 个),或在 64 位系统上分配 24 个字节(每个指针 8 个)。

由于 k 现在是一个指向指针的指针,而不仅仅是一个指针,因此在调用 abc() 时不再需要获取其地址,因此下一行变为:

abc(k);

在 abc 函数中,您不应该手动将值增加到指针。这就是 [] 运算符的用途。您还应该手动将字符串转换为 char*。进行这些更改后,您的 abc 函数应如下所示:

void abc(struct abc **t1){
    t1[0]=(struct abc *)malloc(sizeof(struct abC));
    t1[0]->c=(char *) "Hello";
    
    t1[1]=(struct abc *)malloc(sizeof(struct abC));
    t1[1]->c=(char *) "cool";
    
    t1[2]=(struct abc *)malloc(sizeof(struct abC));
    t1[2]->c=(char *) "Super cool";
}

注意 t1[0]*t1 如何做同样的事情。后者应始终与数组一起使用,以明确 t1 实际上是一个数组。

您应该在 printf() 调用中进行类似的更改,使它们看起来像这样

printf("%s\n",k[0]->c);
printf("%s\n",k[1]->c);
printf("%s\n",k[2]->c);

最后,你应该总是释放你的 malloc 内存!首先释放数组中的每个指针:

free(k[0]);
free(k[1]);
free(k[2]);

然后释放数组本身:

free(k);

养成始终释放数据的习惯将非常有助于防止大型程序中出现痛苦的内存错误。

毕竟,你的最终程序应该是这样的

#include <stdio.h>

struct abc {
    char *c;
};

void abc(struct abc **t1);

int main() {
    struct abc **k = (struct abc **)malloc(sizeof(struct abc *) * 3);
    abc(k);
    
    printf("%s\n",k[0]->c);
    printf("%s\n",k[1]->c);
    printf("%s\n",k[2]->c);
    
    free(k[0]);
    free(k[1]);
    free(k[2]);
    
    free(k);

    return 1;
}

void abc(struct abc **t1){
    t1[0]=(struct abc *)malloc(sizeof(struct abC));
    t1[0]->c=(char *) "Hello";
    t1[1]=(struct abc *)malloc(sizeof(struct abC));
    t1[1]->c=(char *) "cool";
    t1[2]=(struct abc *)malloc(sizeof(struct abC));
    t1[2]->c=(char *) "Super cool";
}

为了回答您的最后一个问题,段错误的行为和时间可能是一件非常棘手且不可预测的事情。它们通常是由未定义的行为引起的,在同一程序的不同执行之间,这些行为甚至可能不同。您应该知道的是,程序中发生段错误的位置与内存中发生的位置无关。

,

分配方法是正确的,但是,您忘记了初始化 k,因此 k 是一个悬空指针。这就是您出现分段错误的原因。我通过添加一个编译器将初始化的变量来应用一个简单的“脏”修复,只是为了证明这是问题所在。

#include <stdio.h>
#include <stdlib.h>

struct abc{ char *c;};

void abc(struct abc **t1);

int main() {
    struct abc _abc[2],*k;
        k = &_abc[0];
    abc(&k);
    printf("%s\n",k->c);

    printf("%s\n",k->c);
    printf("%s\n",(k+1)->c);
    //printf("%s\n",(k+2)->c);

    return 1;
}

void abc(struct abc **t1){


    *t1=(struct abc *)malloc(sizeof(struct abc ));
    (*t1)->c=malloc(50);
    sprintf((*t1)->c,"Hello");
    *(t1+1)=(struct abc *) malloc((sizeof(struct abc )));
    (*t1+1)->c=malloc(50);
    sprintf((*t1+1)->c,"cool");
    *(t1+2)=(struct abc *) malloc((sizeof (struct abc )));
    //(*t1+2)->c="Super cool";
}

编译后

~$ gcc memtest.c -o memtest
~$ ./memtest
Hello
Hello
cool

要了解为什么在 @H_237_5@main 中出现分段错误,而在 abc 中没有,您需要在汇编程序 gcc test.c -S -ggdb3 中转换示例。就我而言,在 ARM64 上,k 被优化掉了。在调用 abc() 之前,编译器插入一个 __stack_chk_guard。这是汇编中的段(ARM64)

    .arch armv8-a
    .file   "memtest_bug.c"
    .text
.Ltext0:
    .align  2
    .global main
    .type   main,%function
main:
.LFB6:
    .file 1 "memtest_bug.c"
    .loc 1 8 16
    .cfi_startproc
    stp x29,x30,[sp,-32]!
    .cfi_def_cfa_offset 32
    .cfi_offset 29,-32
    .cfi_offset 30,-24
    mov x29,sp
    .loc 1 8 16
    adrp    x0,:got:__stack_chk_guard
    ldr x0,[x0,#:got_lo12:__stack_chk_guard]
    ldr x1,[x0]
    str x1,24]
    mov x1,0
    .loc 1 10 9
    add x0,sp,16
    bl  abc

abc()被调用时,k指向一个属于进程的内存区域,所以它仍然是一个有效的段,不会产生段错误。当 main 完成时,编译器插入一个代码来检查堆栈保护,如果检查失败,它会调用 __stack_chk_fail

    mov x3,0
    beq .L3
    bl  __stack_chk_fail
.L3:
    mov w0,w1
    ldp x29,[sp],32
    .cfi_restore 30
    .cfi_restore 29
    .cfi_def_cfa_offset 0
    ret
    .cfi_endproc

此代码检测内存守卫的故障并生成分段错误。这是产生故障时的堆栈(在ARM64上)

#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1  0x0000fffff7e7cd68 in __GI_abort () at abort.c:79
#2  0x0000fffff7eca29c in __libc_message (action=action@entry=do_abort,fmt=fmt@entry=0xfffff7f89f58 "*** %s ***: terminated\n") at ../sysdeps/posix/libc_fatal.c:155
#3  0x0000fffff7f3c600 in __GI___fortify_fail (msg=msg@entry=0xfffff7f89f40 "stack smashing detected") at fortify_fail.c:26
#4  0x0000fffff7f3c5d4 in __stack_chk_fail () at stack_chk_fail.c:24
#5  0x0000aaaaaaaaa8e4 in main () at memtest_bug.c:18

大佬总结

以上是大佬教程为你收集整理的递增指针是否发生在 C全部内容,希望文章能够帮你解决递增指针是否发生在 C所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签: