【问题标题】:How to swap memory between two void pointers in c如何在c中的两个void指针之间交换内存
【发布时间】:2015-04-15 04:54:35
【问题描述】:

我正在尝试交换两个 void 指针指向的内存。我收到一个错误,因为我无法对 void 或 pa 或 pb 元素的大小执行 sizeof(因为您无法取消引用 void 指针)。问题是我无法确定 pa 和 pb 在运行时将是什么数据类型(这应该交换作为参数发送的任何数据类型)。我将如何确定,以便我可以正确使用 malloc?这是我的代码:

void SwapObjects(void *pa, void *pb, size_t size)
{
    void *pc; 
    if ((pc = (malloc(size * sizeof(pa)) == NULL))) //this is wrong         {
        printf("Cannot allocate memory");
        return;
    }
    memcpy(pc, pa, size); //runtime error here
    memcpy(pa, pb, size);
    memcpy(pb, pc, size);
}

【问题讨论】:

  • 您可能应该使用“size”参数而不是“size * sizeof(pa)”。
  • 你得到什么错误,因为sizeof(void) 没有任何意义,但sizeof(pa) == sizeof(void *) 确实有意义。您拥有的代码按原样分配了比需要更多的内存,但除此之外它应该可以工作。

标签: c dynamic-memory-allocation


【解决方案1】:

你的代码是错误的,因为括号

if ((pc = (malloc(size * sizeof(pa)) == NULL)))
/* ^^     ^---------------------------------^^^ 
 * ||________________________________________|| 
 * |__________________________________________|
 */

如您所见,您将malloc(size * sizeof(pa)) == NULL 的结果分配给pc,这是一个指针,这当然是错误的。

应该是

if ((pc = malloc(size)) == NULL)

你分配的内存比需要的多,试图让你的代码紧凑并不能让它变得更好,你可以通过这样做来避免所有这些

pc = malloc(size);
if (pc == NULL)

比较清楚,不会报错。

如果您的代码保持原样,您还需要free(pc),否则每次调用SwapObjects() 时都会发生内存泄漏。

由于它们都只是指针,您只需要重新分配指针,而不是不必要地复制数据

void SwapObjects(void **pa, void **pb)
{
    void *pc; 

    pc  = *pa;
    *pa = *pb;
    *pb = pc;
}

然后

SwapObjects(&pa, &pb);

在您的代码中没有内存泄漏的情况下会产生相同的效果。

如果您确实需要交换内容,请按照上述说明修复您的代码。

【讨论】:

  • 如果我有 50 个指向第一个内存块的指针和 60 个指向第二个内存块的指针怎么办?并且没有任何机制来枚举这些指针。你如何建议我应该去“重新分配指针”?我认为如果 OP 说他们需要物理交换内存内容,那么他​​们有充分的理由物理交换内存内容,而不是指针。
  • @AnT 你能解释一下为什么有人会这样做吗?是他们不喜欢存储数据的位置吗?重要吗,它可以,但在非常特殊的情况下。如果你给出一个理由,请说清楚。
  • @AnT 我认为您的意思是他们通过另一个指针访问它,我没有想到这一点,从上下文来看,除非在问题中指定,否则假设他们不这样做似乎是合理的。
  • 对我来说,假设他们 确实 有其他指针似乎是合理的,除非问题中另有说明。通常习惯于假设更一般(即更糟)的情况。我认为如果 OP 可以交换指针,他们一开始就不会问这个问题。
  • @AnT 你可能是对的,但我的回答解决了这个问题,并建议交换指针,OP 可能会接受或不接受。
【解决方案2】:

你可以完全避免使用malloc()

void SwapObjects(void *pa, void *pb, size_t size) {
    unsigned char tmp;
    unsigned char *a = pa, *b = pb;
    while(size--) {
        tmp = *a;
        *a++ = *b;
        *b++ = tmp;
        }
    }

【讨论】:

  • 你为什么不用memcpy
  • @iharob:在这种情况下你会如何使用memcpy
  • OP 的问题只有我的回答中提到的问题,如您所见,但 OP 正确使用 memcpy() 虽然不是 malloc()
  • @iharob:是的,但这个答案的重点是如何在没有运行时大小的缓冲区的情况下做同样的事情。 IE。如何在没有malloc 的情况下解决问题。如果有s no malloc`(这就是重点),我认为memcpy 在这里没有任何用处。
【解决方案3】:

我不完全确定我理解你的意图。

  1. 您是否希望指针 A 引用指针 B 的内存,反之亦然? (使用你的函数签名):

    void SwapObjects( void *pa, void *pb )
    {
      void *pTemp = pa;
      pa = pb;
      pb = pTemp;
    }
    
  2. 是否要将每个指针引用的内存复制到另一个缓冲区?

    请注意,不能保证这在一般情况下会起作用,因为此函数无法知道每个指针所引用的池的大小——程序员无法获得此信息通过 C 中任何受支持的语言构造。编译器如何跟踪池的大小取决于特定的编译器,通常是通过将信息存储在与 malloc() 给出的指针地址的负偏移量处。

    这意味着您需要让调用者提供您必须盲目信任的函数缓冲区大小(== 不安全!)。您可能会截断数据,或者更糟糕的是,读取缓冲区内有效数据的末尾、读取缓冲区末尾或写入缓冲区末尾之后。除非此函数可以保证这些缓冲区大小(即函数本身分配缓冲区,或者您与调用者有某种形式的强合同),否则您应该认为此代码是不安全的。

    假设参数 sizeA 和 sizeB 以字节为单位,而不是元素。

    最后一点,别忘了 free() 你的 malloc() 的!

    /* This function is unsafe! Buffer sizes are not validated */
    void SwapOpbjects(void *pa, size_t sizeA, void *pb, size_t sizeB)
    {
      /* TODO: Ensure pa and pb are both non-NULL */
      /* TODO: Ensure sizeA and sizeB are both > 0 */
    
      void *pTemp = malloc( sizeA );
      if( !pTemp )
      {
        printf("malloc() failed!");
        return;
      }
    
      memcpy( pTemp, pa, sizeA ); /* Safe, since we allocated pTemp ourselves */
      memcpy( pa, pb, sizeB );    /* Unsafe! let's hope pa's pool is big enough to hold sizeB bytes; or you could risk truncating sizeB by only copying sizeA bytes...  Neither choice is a great one */
      memcpy( pb, pTemp, sizeA ); /* Unsafe!  As per above. */
    
      free( pTemp );
    }
    

建议:坚持使用解决方案 #1,或者如果这不可行,请告诉我们用例,以便解决方案成为最佳实践示例。

祝你好运!

【讨论】:

    猜你喜欢
    • 2013-07-09
    • 1970-01-01
    • 2016-10-24
    • 2021-01-15
    • 1970-01-01
    • 1970-01-01
    • 2019-02-03
    • 1970-01-01
    • 2021-03-22
    相关资源
    最近更新 更多