【问题标题】:C: Pointer arithmetic and malloc() - NO GO?C:指针算术和 malloc() - 不行吗?
【发布时间】:2020-07-22 13:26:13
【问题描述】:

在熟悉指针之后,我遇到了使用 malloc() 和 free() 进行动态内存分配的部分。我想确认或更正我对这个话题的理解。

直到现在,我才明白指针的巨大好处有两个:

  1. 通过引用调用(即可以使用指针访问和更改函数外部的变量,而无需全局变量)。
  2. 使用指针算法,它是一种非常方便且代码高效的方式来遍历数组(例如,作为字符串的 char 数组),访问和操作数据。

谈到 malloc(),我觉得如果指针地址没有被重置,指针算术会变得非常危险。给定下面的示例,我使用 malloc() 创建了两个指针 ptr 和 ptr1。 我理解这两个 malloc() 函数分配了两个内存块,每个都和 size*sizeof(int) 一样大,所以这是保留内存,这两个块的第一个元素的地址给 ptr 和 ptr1。

使用第一个 for 循环,我使用指针将值分配到内存位置。 ptr 使用指针算术,ptr1 使用数组算术(如果我可以这样称呼的话)。

在for循环结束时,ptr不指向保留内存块的第一个元素的地址,必须重新设置回来才能指向第一个元素的地址。

第二个 for 循环打印两个内存块中的数据存储。在那里,我没有将 ptr 重置为指向内存中第一个元素的地址。

现在有个大问题: 使用 free(ptr),free() 接收指向某个地址的指针(而不是保留的内存块的起始地址)。我是否理解正确,写free(ptr),我现在会释放一个不同的大小*sizeof(int)的内存块,我可能会释放一些不应该释放的敏感数据?

理解正确吗?如果是这样,在将指针与 malloc() 结合使用时,是否建议始终使用数组算术?

谢谢你, 亚历克斯

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

int main()
{
int size = 0;
printf("Enter the array size: ");
scanf("%d",&size);

int * ptr = (int *)malloc(size*sizeof(int));
int * ptr1 = (int *)malloc(size*sizeof(int));

int i = 0;
// First for loop
for( ; i<size;i++)
{
    *ptr = i;
    ++ptr;
    *(&ptr1[i]) = i;
}

ptr = ptr-size; // Resetting to the start address

// Second for loop
for(i = 0; i<size;i++)
{
    printf("%d\t\t",*ptr);
    ptr++;
    printf("%d\n",*(&ptr1[i]));
}

free(ptr);  // Is the correct memory block now freed?
free(ptr1);
return 0;
}

【问题讨论】:

  • 代码更改ptr,然后将一个有效的随机值传递给free。事后试图调整它是糟糕的设计:如有必要,保留一份副本。您必须将malloc 返回的精确 值传递给free,无论哪个 变量保存它。用于获取内存的实际变量没有内存。
  • 规则是你必须把它在malloc中返回的地址给free,就是这样。如果您操纵指针使其指向其他地方,那么您的工作就是跟踪原始地址。无论您是操纵指针还是保留另一个指针,都没关系。请记住始终freemalloc 提供给您的地址相同。
  • 当你试图理解这样的代码时,我发现在调试器中单步执行它并查看每一行如何更改变量、内存等很有帮助,这比看到大量 printfs 更好滚动屏幕。

标签: c pointers malloc free memory-mapped-files


【解决方案1】:

首先,这些语句中使用了多余的运算符

*(&ptr1[i]) = i;

printf("%d\n",*(&ptr1[i]));

它们等价于

ptr1[i] = i;

printf("%d\n", ptr1[i] );

如果指针的值与调用 malloc 返回的值不同,则为此类指针调用 free 会导致未定义的行为。

注意这个循环中的那个

for( ; i<size;i++)
{
    *ptr = i;
    ++ptr;
    *(&ptr1[i]) = i;
}

你可以显式地使用指针 ptr 的指针算法

for( ; i<size;i++)
{
    *( ptr + i ) = i;
    *(&ptr1[i]) = i;
}

在这种情况下,指针 ptr 本身的值不会改变。

【讨论】:

    【解决方案2】:

    您的程序有未定义的行为。传递给free() 的指针值必须完全等于malloc()calloc()realloc() 获得的值。来自cppreference.com

    如果 ptr 的值不等于某个值,则行为未定义 之前由 malloc()、calloc()、realloc() 或 aligned_alloc() 返回 (自 C11 起)。

    所以保留一个指向您的分配的纯正指针以传递给free(),并使用一个副本进行指针运算。

    【讨论】:

      猜你喜欢
      • 2014-11-13
      • 1970-01-01
      • 2016-07-30
      • 1970-01-01
      • 2012-07-27
      • 1970-01-01
      • 2010-10-20
      相关资源
      最近更新 更多