精华内容
下载资源
问答
  • VS写C语言报错无法读取内存

    千次阅读 2018-11-17 20:58:54
    错误就在于给指针分配内存的时候没写malloc..... 就像上图一样,并不会报错!所以要加上mallco

    错误就在于给指针分配内存的时候没写malloc.....

    就像上图一样,并不会报错!所以要加上mallco

    展开全文
  • [img=https://img-bbs.csdn.net/upload/201705/05/1493915975_574486.png][/img] 代码和问题如图。。。小白很无奈
  • C语言中的内存管理

    2008-11-13 19:26:00
    相比静态地分配内存空间,使用动态内存分配具有明显的优势:1, 分配空间的大小够精确: 设想一个读取用户输入行的程序, 如果使用静态分配的数组作为buffer, 那么, 你如何确定该数组的长度呢? 太大或太小都不合适. 因为...
    相比静态地分配内存空间,使用动态内存分配具有明显的优势:

    1, 分配空间的大小够精确: 设想一个读取用户输入行的程序, 如果使用静态分配的数组作为buffer, 那么, 你如何确定该数组的长度呢? 太大或太小都不合适. 因为你无法事先知道用户输入字符串的长度. 而使用动态内存分配就精准多了.

    2, 静态分配的空间大小无法更改, 而动态分配的内存大小是可调的.

    所以, 理解C语言中的动态内存分配对于编写实用, 有效, 安全的程序来说必不可少. 本文假设你使用C语言编程, 且使用GNU/Linux系统. (其实由于现在的许多系统都是POSIX兼容的, 本文的内容使用于任何操作系统, 只是其中提到的某些工具仅存于GNU/Linux上.)

    要理解内存管理, 首先要理解程序在内存中的布局, 既: 内存程序映像. 可参考本blog的GNU/Linux平台的C程序开发及程序运行环境

    标准C中的内存管理函数

    函数原型如下:

    #include <stdlib.h>

    void *malloc(size_t size);
    void *calloc(size_t nobj, size_t size);
    void *realloc(void *ptr, size_t newsize);
    若返回的指针=NULL, 则失败, 否则成功.

    void free(void *ptr);
                                                                                      ISO C


    上表列出了标准C规定的四个常用内存管理函数, 一般而言, 这4个函数已经足够我们进行内存管理了.

    malloc(), calloc(), realloc()返回的指针若不为NULL, 那么该指针指向被分配数据块中的第一个元素. 并且, 保证该指针能针对各种数据类型满足对齐要求.

    void *malloc(size_t size);

    调用malloc()的步骤
    1, 针对你想要存放数据的数据结构, 声明一个指向它的指针.
    2, 计算你需要分配的字节数. 通常利用sizeof(数据结构) * n, n为你要使用的数据结构的个数.
    3, 调用malloc()分配内存, 并将它所返回的通用指针(void *)显式地映射为指向该数据结构的指针, 并检查malloc()是否返回了NULL, 若返回值为NULL, 则进行错误处理.

    实现代码
    struct num {
        int x, y, z;
    };
    struct num *p;
    int n;

    if ((p = (struct num *)malloc(n * sizeof(struct num))) == NULL) {
        错误处理;
    }
    使用p指向的内存; (记得初始化!)

    标准C中规定, void *p是一个通用指针, 可以将它赋予任何类型的数据. 但在这里最好还是显式地将它的类型映射为需要分配的数据类型. why? 先看看下面替代上面使用malloc()函数的语句:
    if ((p = malloc(n * sizeof(*p))) != NULL)
    这里将sizeof的参数换成了*P, 这样, 即便p被修改, 指向了不同的数据结构, sizeof也能计算正确的字节数. 这里省略了类型映射, 但加上它以后, 能够在p指向不同的数据结构后, 编译时给出警告信息.
    总之, 我们使用这样的语句来调用malloc():
    if ((p = (ds *)malloc(n * sizeof(*p))) == NULL)
    其中(ds *)将通用指针显式地映射到要分配的数据类型.

    另外, 传统c中使用char *作为通用指针, C++要求对malloc()的返回值进行显式的映射.

    void *realloc(void *ptr, size_t newsize);

    使用realloc()可以调整之前分配的数据块大小. 包括增加或则减小. 一般而言不用减小已分配数据块的大小.

    关于realloc()的原型, 有几点值得注意:
    1, newsize是调整数据块大小后最终的值, 并非差量.
    2, 若ptr != NULL && nesize == 0, 则 realloc(p, 0)等价于free(p).
    3, ptr指向需要调整的数据块, 若ptr == NULL, relalloc(NULL, newsize)等价于malloc(newsize).

    虽然可以用realloc()实现free()和malloc()的功能, 但不推荐这样做. 还是使用标准的接口比较合适.

    调用realloc()的步骤:
    1, 计算你新需要的字节数.
    2, 找到指向你需要调整的数据块的指针(它是malloc()或calloc()甚至realloc()的返回值.), 并将它和新的字节大小传递给realloc(). 注意不要用增量!
    3, 调用realloc()分配内存, 并将它所返回的通用指针(void *)显式地映射为指向该数据结构的指针, 并检查malloc()是否返回了NULL, 若返回值为NULL, 则进行错误处理.

    注意: GNU Coding Standards规定: 即便realloc()失败, 之前分配的数据块也会保持不变, 可以继续使用.

    实现代码
    这里继续上述malloc()中的代码, 假设之前分配的n个num结构不够, 还需要再分配m个:
    struct num *q;
    int newsize = (n+m) * sizeof(*p);

    if ((q = (struct num *)realloc(p, newsize)) == NULL) {
        错误处理;
    }
    p = q;
    继续使用p;

    注意: realloc()返回的地址赋给了一个新的指针q. 在调用完realloc()之后, 又将q的值赋给p , 继续使用p. 为何如此麻烦呢?  原因有二:

    (1)看看上面的框框, GNU保证即便realloc()返回NULL, 之前调用malloc()分配给p的数据块也能使用, 但若直接把realloc()的返回值赋给p, 可能令p = NULL, 使得之前p指向的数据段无法使用.

    (2)使用realloc()时, 脑子里应该时刻铭记一点: 由于对之前的数据块大小进行了调整, realloc()可能将以前的数据块挪到内存中别的位置. 考虑增大数据块的情况: 若之前分配的数据块所在的内存空间所剩的空间不够, 那么realloc()会将以前的数据块拷贝到内存中其他位置, 并释放之前分配的数据块. 这样之前的p就指向了无效的区域. 即便调用realloc()来减小数据块, 该数据块也可能被移到内存中的其他位置!

    某个已分配的数据块b1, 调用realloc()调整b1大小得到b2之后, 不能假设b1和b2的第一个元素在同一位置. 指向b1的所有指针必须被更新!
    引用原b1数据块中的元素有两种途径:
    1, 使用数组下标.
    2, 使用被更新后的指针. 绝不能使用以前指向p1的指针!

    void *calloc(size_t nobj, size_t size);

    calloc()可视为malloc()的一个封装, 下面是它可能的一个实现:
    void *calloc(size_t nobj, size_t size)
    {
        void *p;
        size_t total;

        total = nobj * size;
        if ((p = malloc(total)) != NULL) {
           memset(p, '/0', total);

        return p;
    }

    调用calloc()的方法与malloc()相同. calloc()与malloc()的区别在于两点:
    1, calloc()将分配的内存数据块中的内容初始化为0. 这里的0指的是bitwise, 既每个位被清0, 具体的数值由要联系数据结构中各元素的类型.

    2, 传递给calloc()的参数有2个, 第一个是想要分配的数据结构的个数, 第二个是数据结构的大小.

    如果传递给malloc()或calloc()的size = 0, 标准C并未规定返回的指针一定为NULL, 它可能为非NULL. 但是这种情况下不能引用该指针.

    void free(void *ptr);

    在完成对动态分配的数据块的使用之后, 要
    通过调用free()来释放它. 这里所说的"释放"是指将该数据块占用的内存放回到堆中, 以后再调用malloc(), calloc()或realloc()时可以利用该数据块占用的内存段. 注意free()并不能够改变进程地址空间的大小, 被释放的内存仍位于堆空间中.

    如果不及时释放内存, 会引发内存泄露(memory leaks), 特别是运行时间比较长的程序要注意这个问题, 如果发生了内存泄露, 系统即便不因为缺少内存资源而崩溃, 也会由于内存抖动(memory thrashing)而性能下降.

    调用free()的方法:
    free(p);
    p = NULL;

    调用free()时, 有几点注意:
    1, p必须指向由malloc(), calloc()或realloc()返回的地址. 即传递给free()的参数必须是数据块第一个元素的地址.  因为malloc()的实现往往在分配的数据块的首部存储一些用来管理分配的数据块的记账信息. 如果不将数据块首部地址传递给free(), free()无法知道数据块的具体信息, 也就无法释放. 把NULL传递给free()是合法的, free()不起任何作用.

    NULL == ((void *)0), 在现代系统上, 地址0不在进程地址空间之内, 引用0地址会引发段错误.

    2, 谨防"dangling pointer(野指针)", 当p指向的数据块被释放后, p就成为了一个野指针. 如果再次通过p引用数据就存在问题了. p可能指向了内存中别的位置.( 如果在p被释放之后没有调用内存分配函数, p可能还指向原来的数据块, 但该情况不确定). 所以, 在调用free(p);之后, 要紧接着将p设为NULL. 这样如果引用p, 就会马上引起段错误. 不会干扰程序的其他地方.

    3, 一个数据块只能被释放一次, 如果对同一数据块释放多次, 会引发问题. (多次调用free(NULL)不存在任何问题.)

    4, 被释放的内存依然位于进程地址空间, 用于以后调用malloc(), calloc(), realloc()返回的数据块.


    在栈上分配内存: alloca()

    前面的malloc(), calloc(), realloc()都在堆上分配内存, 需要显式地释放所分配的内存. 如果使用alloca()在栈上分配内存, 由于每次函数返回时都会释放它所在的栈空间,  alloca()所分配的内存会像动态变量一样被自动释放.

    alloca()的原型:

    #include <alloca.h>
    void *alloca(size_t size);

    不推荐使用alloca(), 因为它不属于ISO C或POSIX标准, 依赖于具体的系统和编译器, 即便在支持它的系统上, 它的实现也有bug.


    brk()和sbrk()系统调用

    在UNIX系统中, malloc(), calloc(), realloc(), free()这4个函数都是在brk()和sbrk()这两个系统函数基础上实现的.  在应用程序中, 极少见到这两个函数, 这里对它们做一个简单介绍, 并利用它们来查看进程地址空间信息.

    brk(), sbrk()的原型:

    #include <unistd.h>
    int brk(void *end_data_segment);
    void *sbrk(intptr_t increment);

    brk()j将进程地址空间的data段尾(既内存程序映像的堆尾)设置为end_data_segment所指向的位置. 若成功, 返回0, 否则返回-1.

    sbrk()使用差量来调整进程地址空间data段尾的位置, 并返回之前data段尾的地址.

    下面看看这样一个程序, 它显示进程地址空间的相关信息:

         1    /*
         2     * Show address of code, data and stack sections,
         3     * as well as BSS and dynamic memory.
         4     */
         5   
         6    #include <stdio.h>
         7    #include <malloc.h>        /* for definition of ptrdiff_t on GLIBC */
         8    #include <unistd.h>
         9    #include <alloca.h>        /* for demonstration only */
        10   
        11    extern void afunc(void);    /* a function for showing stack growth */
        12   
        13    int bss_var;            /* auto init to 0, should be in BSS */
        14    int data_var = 42;        /* init to nonzero, should be in data */
        15   
        16    int
        17    main(int argc, char **argv)   
        18    {
        19        char *p, *b, *nb;
        20        int i;
        21        printf("Text Locations:/n");
        22        printf("/tAddress of main: %p/n", (void *)main);
        23        printf("/tAddress of afunc: %p/n", afunc);
        24   
        25        printf("Stack Locations:/n");
        26        afunc();
        27   
        28        p = (char *) alloca(32);
        29        if (p != NULL) {
        30            printf("/tStart of alloca()'ed array: %p/n", p);
        31            printf("/tEnd of alloca()'ed array: %p/n", p + 31);
        32        }
        33   
        34        printf("Data Locations:/n");
        35        printf("/tAddress of data_var: %p/n", & data_var);
        36   
        37        printf("BSS Locations:/n");
        38        printf("/tAddress of bss_var: %p/n", & bss_var);
        39   
        40        nb = sbrk((ptrdiff_t) 0);
        41        printf("Heap Locations:/n");
        42        printf("/tInitial end of heap: %p/n", nb);
        43        b = sbrk((ptrdiff_t) (32));    /* lower heap address */
        44        printf("/t  sbrk return : %p/n", b);
        45       
        46   
        47        nb = sbrk((ptrdiff_t) 0);
        48        printf("/tNew end of heap: %p/n", nb);
        49   
        50        b = sbrk((ptrdiff_t) -16);    /* shrink it */
        51        nb = sbrk((ptrdiff_t) 0);
        52        printf("/tFinal end of heap: %p/n", nb);
        53       
        54        printf("Command-Line Arguments:/n");
        55        for (i = 0; argv[i] != NULL; i++)
        56          printf("/tAddress of arg%d(%s) is %p/n", i, argv[i], &(argv[i]));
        57   
        58        return 0;
        59    }
        60   
        61    void
        62    afunc(void)
        63    {
        64        static int level = 0;        /* recursion level */
        65        auto int stack_var;        /* automatic variable, on stack */
        66   
        67        if (++level == 3)        /* avoid infinite recursion */
        68            return;
        69   
        70        printf("/tStack level %d: address of stack_var: %p/n",
        71                level, & stack_var);
        72        afunc();            /* recursive call */
        73    }

    在Linux, x86系统中, 代码段开始于 0x08048000; 栈底地址开始于0xc0000000.

    展开全文
  • 使用的malloc函数新创立的结构体 中的string类型出现了问题,即读取字符串的字符时出错,无法读取内存 最后发现是新建节点时出现了错误:(C语言中没有string类 用malloc无法识别) TreeNode * t = (TreeNode *) ...

    最近在学习编写编译器时用vs2013遇到一个问题:

    使用的malloc函数新创立的结构体 中的string类型出现了问题,即读取字符串的字符时出错,无法读取内存

    最后发现是新建节点时出现了错误:(C语言中没有string类 用malloc无法识别)

    TreeNode * t = (TreeNode *) malloc(sizeof(TreeNode)); (我copy书中的源码,用的c语言)

    但是为了使用方便,在结构体中使用了string类

     typedef struct treeNode
    {
      struct treeNode * child[MAXCHILDREN];
      struct treeNode * sibling;
      TokenType op;
      int val;
      string name;
      ExpKind expkind;
    }TreeNode;

    所以用C语言的malloc函数无法为string类对象分配正确的内存,因此出现了错误

    修改使用C++的new函数来创建新的树节点则问题消失:

    TreeNode * t = new TreeNode;

     

    网上搜集的资料:

    对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。
    因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清理与释放内存工作的运算符delete。注意new/delete不是库函数。
    我们不要企图用malloc/free来完成动态对象的内存管理,应该用new/delete。由于内部数据类型的“对象”没有构造与析构的过程,对它们而言malloc/free和new/delete是等价的。

    上面的回答解决了我的问题:
    结构体中有string类 ,string类的构造函数在malloc时无法执行,出现我上面的问题
    new可以认为是malloc函数加构造函数的执行。
    参考博文 http://blog.csdn.net/zjc156m/article/details/16819357
    http://blog.csdn.net/hazir/article/details/21413833

    转载于:https://www.cnblogs.com/MYJ55/p/6765587.html

    展开全文
  • C语言中的malloc申请内存失败的原因

    千次阅读 2019-04-11 16:26:40
    今天在写C语言的时候,发现一个malloc函数的返回值总是NULL,无法申请内存,导致异常:读取位置时候发生访问冲突。 查询了很多解决方法,在此归纳一下malloc函数无法分配内存的原因: 内存不足(个人认为目前的...

    今天在写C语言的时候,发现一个malloc函数的返回值总是NULL,无法申请内存,导致异常:读取位置时候发生访问冲突。

    查询了很多解决方法,在此归纳一下malloc函数无法分配内存的原因:

    1. 内存不足(个人认为目前的代码量对比计算机的内存性能还不够出现这样的错误)
    2. 前面程序使用malloc函数时候发生了内存访问越界,即前面的malloc相关函数调用出现问题,导致接下来的malloc函数分配内存时候发生信息错误,无法正常调用

    问题:

    对于本次写的代码,首先构建了两种结构体:

    //定义顶点结构
    typedef struct gnode *ptrtognode;
    struct gnode
    {
    	int Nv;//顶点个数
    	int Ne;//边数
    	weighttype weight[MAX][MAX];//定义邻接矩阵
    };
    typedef ptrtognode Mgraph;//定义的邻接矩阵
    
    //定义边结构
    typedef struct edge *ptrtoedge;
    struct edge
    {
    	vertex v1, v2;
    	weighttype weight;
    };
    typedef ptrtoedge Edge;
    

    在定义结构体变量,使用malloc分配内存的时候,一开始定义如下:

    Mgraph M;
    M = (Mgraph)malloc(sizeof(ptrtognode));
    ......
    
    Edge e;
    e = (Edge)malloc(sizeof(ptrtoedge));
    ......
    

    程序在运行到第二个malloc后,会返回NULL,之后如果给该变量赋值,就会发生访问冲突,研究了很久也不知道怎么回事,后来突然发现为了偷懒在sizeof()函数中取的是结构体指针的变量大小,而不是结构体的变量大小,这样第二次的malloc函数就会出现问题。

    问题解决:

    将上述代码改为:

    Mgraph M;
    M = (Mgraph)malloc(sizeof(struct gnode));
    ......
    
    Edge e;
    e = (Edge)malloc(sizeof(struct edge));
    ......
    

    问题解决!

    这里意识到:结构体指针的大小与结构体的大小是不一样的,可以看下面这个程序:

    #include<stdio.h>
    
    typedef struct a *ptrtoa;
    struct a
    {
    	int n1, n2;
    };
    typedef ptrtoa A;
    
    int main()
    {
    	printf("%d %d %d\n", sizeof(struct a), sizeof(ptrtoa), sizeof(A));
    	return 0;
    }
    

    程序的输出结果为:

    8 4 4


    另外关于更多有关malloc函数的相关知识,参照网上大神这个博客:

    C语言之内存的申请malloc() 和释放free()

    展开全文
  • C语言编程预备知识

    2017-11-18 10:23:15
    读取外部文件时,外部文件首先由硬盘存入内存条,之后再由CPU调用(CPU无法直接读取硬盘中的数据),之后通过显卡显示出来. 主板是用来连接CPU,内存条,硬盘,显卡之间关系的硬件 2.HelloWorld程序如何运行起来的 先编译...
  • C语言中,遇到的奇奇怪怪的问题汇总,开发工具为:VS2019 ...无法读取内存> 2.使用未初始化的变量: 在利用结构体作为参数时,要注意如果使用不当,在调用init()初始化函数结果不一定会影响到外面的变量,这就导致了外面
  • 每次都读取内存(主内存)中的值,而不是CPU的Register(寄存器、高速缓冲、工作内存),即使CPU运行的指令是对 同一variable操作 Literally 语义 volatile: 挥发物;易挥发的,反复无常的 in program conte...
  • C语言屏幕函数

    2007-10-03 21:40:20
    如果检测失败,那么大多数BIOS将无法调入RAM中,开机后无任何反应,微机黑屏。自检程序允许必要的附加卡上的BIOS程序首先进入它们自己的系统并初始化,但在此之前,主板上的BIOS必须找到附加卡上的BIOS程序,才能在...
  • 你必须知道的495个C语言问题

    千次下载 热门讨论 2015-05-08 11:09:25
    这导致空间浪费而且无法与外部数据文件进行“二进制”读写。能否关掉填充,或者控制结构域的对齐方式? 2.14 为什么sizeof返回的值大于结构大小的期望值,是不是尾部有填充? 2.15 如何确定域在结构中的字节偏移...
  • o 3.10 我的编译器在结构中留下了空洞, 这导致空间浪费而且无法与外部数据文件进行 "二进制" 读写。能否关掉填充, 或者控制结构域的对齐方式? o 3.11 为什么 sizeof 返回的值大于结构的期望值, 是不是尾部有填充? ...
  • 二进制文件虽然也可在屏幕上显示, 但其内容无法读懂。C系统在处理这些文件时,并不区分类型,都看成是字符流,按字节进行处理。 输入输出字符流的开始和结束只由程序控制而不受物理符号(如回车符)的控制。 因此也把...
  • c语言中,是无法对空指针进行数据的读取和写入的,这是受到操作系统的保护,如果要去访问 或者是写入数据,程序会直接挂掉的;所以这里要进行判断,是否对操作的指针已经进行内存分配了, 是否可以对它们进行...
  • 只要按照指针指到头部地址即可正常读取出来,但是由于处理器读取int 或者 float 数据类型比较要求数据地址是四字节对齐的,而我们这个数组存放在内存中是以两个字节对齐的,这就导致了CPU无法读取数据并死机在了读取...
  • printf("无法读取文件.\n"); exit(0); } while(j!=NULL) { fscanf(f,"\t\t%s\t\t\t%f\n",j->food,&j->price); printf("\t\t%s\t\t\t%f\n",j->food,j->price); j=j->next; } fclose(f); } void ...
  • 《你必须知道的495个C语言问题》

    热门讨论 2010-03-20 16:41:18
    这导致空间浪费而且无法与外部数据文件进行“二进制”读写。能否关掉填充,或者控制结构域的对齐方式? 27  2.14 为什么sizeof返回的值大于结构大小的期望值,是不是尾部有填充? 28 2.15 如何确定域在结构中的...
  • // 读取影像数据到内存上 int numread = fread(src_image,sizeof(unsigned char),width*height,stream); printf("共读入%d字节的数据\n",numread); // 计算正弦、余弦值 cossigma = cos(sigma*pi/180); ...
  • 使用的malloc函数新创立的结构体 中的string类型出现了问题,即读取字符串的字符时出错,无法读取内存 最后发现是新建节点时出现了错误:(C语言中没有string类 用malloc无法识别) TreeNode * t = (TreeNode *) ...
  • 然后又使用一些内存分配技巧使namestr数组用起来好像有多个元素,namelen记录了元素个数。它是怎样工作的?这样是合法的和可移植的吗? 23  2.8 我听说结构可以赋给变量也可以对函数传入和传出。为什么K&R1却明确...
  • 这导致空间浪费而且无法与外部数据文件进行“二进制”读写。能否关掉填充,或者控制结构域的对齐方式?  2.14 为什么sizeof返回的值大于结构大小的期望值,是不是尾部有填充?  2.15 如何确定域在结构中的字节...
  • 然后又使用一些内存分配技巧使namestr数组用起来好像有多个元素,namelen记录了元素个数。它是怎样工作的?这样是合法的和可移植的吗? 2.8 我听说结构可以赋给变量也可以对函数传入和传出。为什么K&R1;却明确说明...
  • 你必须知道的495个C语言问题(PDF)

    热门讨论 2009-09-15 10:25:47
    2.10 我的编译器在结构中留下了空洞, 这导致空间浪费而且无法与外 部数据文件进行”二进制” 读写。能否关掉填充, 或者控制结构域 的对齐方式? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 2.11...
  • 这导致空间浪费而且无法与外部数据文件进行“二进制”读写。能否关掉填充,或者控制结构域的对齐方式? 56 2.14 为什么sizeof返回的值大于结构大小的期望值,是不是尾部有填充? 57 2.15 如何确定域在结构中的字节...
  • 这导致空间浪费而且无法与外部数据文件进行“二进制”读写。能否关掉填充,或者控制结构域的对齐方式? 56 2.14 为什么sizeof返回的值大于结构大小的期望值,是不是尾部有填充? 57 2.15 如何确定域在结构中的字节...
  • np.memmap读取大文件

    2019-09-26 20:45:59
    Numpy中的ndarray是一种新形式的Python内建类型。因此,它可以在需要时被继承。...当一个特别大的数组无法常驻内存时,np.memmap非常有用。 参数类型: filename:字符串、文件或者path dtype:...
  • C程序中的内存管理

    2010-01-12 22:58:00
    相比静态地分配内存空间,使用动态内存分配具有明显的优势:1,分配空间的大小够精确:设想一个读取用户输入行的程序,如果使用静态分配的数组作为buffer,那么,你如何确定该数组的长度呢?太大或太小都不合适.因为你无法...

空空如也

空空如也

1 2 3 4
收藏数 77
精华内容 30
关键字:

c语言无法读取内存

c语言 订阅