首页 > 解决方案 > do 指针总是比指针数组等指针更动态

问题描述

我有这个代码

int main()
{


char **ppi;
ppi = malloc(sizeof(char *)*1);
ppi[0] = malloc(sizeof(char)+1);
ppi[1] = malloc(sizeof(char)+1);
ppi[2] = malloc(sizeof(char)+1);
strcpy(*ppi,"1");
strcpy(*(ppi+1),"2");
strcpy(*(ppi+2),"3");
printf("%s %s %s\n", *ppi,*(ppi+1),*(ppi+2));

char *pp[1];
pp[0]=malloc(sizeof(char)+1);
pp[1]=malloc(sizeof(char)+1);
pp[2]=malloc(sizeof(char)+1);

strcpy(*pp,"1");
strcpy(*(pp+1),"2");
strcpy(*(pp+2),"3");
printf("%s %s %s\n",*(pp+0),*(pp+1),*(pp+2) );
  /*char *(*tags)[2] = malloc (20 * sizeof *tags);
  for(int i=0;i<20;i++)
  {
    *(*(tags+i)+0)=*(tags_v+i);
    tags[i][1]=tags_t[i];
    //printf("%s %s \n",*(*(tags+i)+0),*(*(tags+i)+1));
  }*/
//  printf("%s\n",(*tags_1)[0]);
  return 0;
}

但是我收到错误stack smashing detected,我认为这是错误的,或者在索引 2 处的这一行之后对指针数组进行的pp[2]=malloc(sizeof(char)+1);任何访问。pp但是我可以很容易地增加指针指针的元素数量。这是否意味着即使指针数组也是一种指针,但它们也是数组,所以增加元素数量会导致堆栈粉碎等问题。

我可以在不使用指针数组的情况下通过指针数组摆脱这个错误吗?我相信它的堆栈错误,可能是因为索引是基于指针数组的堆栈。如果我将指针数组创建为全局指针会怎样?

这个问题是相关 的,我是否需要为指针分配空间以及内存区域的空间,其地址将保存在指向指针和 realloc 的指针中

标签: c

解决方案


如果问题是“我是否需要为……分配空间”,答案是肯定的 否定的。真正的问题是,“分配”是什么意思。

存储可以分配在堆栈上(通过声明自动分配)或堆上(malloc 和朋友)。

指针只是保存特定内存块地址的存储。如前所述,地址变量(指针)也可以分配在栈上或堆上。

例子:

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

int main()
{
    //stack allocation
    int i = 42;

    //store the address of the variable 'i' in 'pi'
    void *pi = &i; //<- 'pi' is allocated on the stack

    //print the value of the address to stdout
    printf("the address of i: %p\n", pi);

    //store the address of the variable 'pi' in 'pp' (example of pointer to pointer)
    void *pp = &pi; //<- 'pp' is allocated on the stack
    printf("the address of pi: %p\n", pp);

    //here we have two allocations:
    //- 'ptr' is allocated on the stack
    //- malloc allocates 1 byte on the heap and returns the address of that memory block, which is stored in 'ptr'
    void *ptr = malloc(1);

    printf(
        "the address of ptr: %p\n"
        "the address of the allocated memory area: %p\n", 
        &ptr,
        ptr
    );

    //allocate storage on the heap large enough to hold a pointer
    void **pptr = malloc(sizeof(void*)); //'pptr' is allocated on the stack
    //allocate 1 byte on the heap and store the address in the memory area from above
    *pptr = malloc(1);

    printf(
        "the address of pptr: %p\n"
        "the address of the allocated memory to store the pointer: %p\n" 
        "the address that is stored in pptr (via malloc(1)): %p\n",
        &pptr,
        pptr,
        *pptr
    );

    //array of pointer of size 3
    void *pa[3]; //heap version: malloc(sizeof(void*) * 3)
    pa[0] = malloc(1);
    pa[1] = malloc(1);
    pa[2] = malloc(1);

    printf(
        "address of the array: %p\n"
        "address of the first element: %p\n"
        "address of the second element: %p\n"
        "address of the third element: %p\n"
        "address stored in the first element: %p"
        "address stored in the second element: %p"
        "address stored in the third element: %p",
        &pa, &pa[0], &pa[1], &pa[2], pa[0], pa[1], pa[2]
    );

    return 0;
}

栈粉碎/缓冲区溢出问题:

//declare a pointer to pointer to char
char **ppi; 
//allocate space large enough to hold a (one) pointer to char
ppi = malloc(sizeof(char *)*1);
ppi[0] = ... //ok, same as *ppi
ppi[1] = ... //not ok, we allocated space only for 1 (one) pointer
ppi[2] = ... //not ok, we allocated space only for 1 (one) pointer

//allocate an array of pointers to char on the stack, with size of 1 (one)
char *pp[1];
pp[0] = ... //ok, array has size 1
pp[1] = ... //not ok, array has size 1
pp[2] = ... //not ok, array has size 1

推荐阅读