如何在c中的两个空指针之间交换内存

如何在c中的两个空指针之间交换内存,c,dynamic-memory-allocation,C,Dynamic Memory Allocation,我试图交换由两个空指针指向的内存。我得到一个错误,因为我不能对一个空进行sizeof,或者对pa或pb元素的大小进行计算(因为不能取消引用一个空指针)。问题是我无法确定在运行时pa和pb的数据类型(这应该交换作为参数发送的任何数据类型)。我如何确定这一点,以便正确使用malloc?这是我的密码: void SwapObjects(void *pa, void *pb, size_t size) { void *pc; if ((pc = (malloc(size * sizeo

我试图交换由两个空指针指向的内存。我得到一个错误,因为我不能对一个空进行sizeof,或者对pa或pb元素的大小进行计算(因为不能取消引用一个空指针)。问题是我无法确定在运行时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);
}

由于括号的原因,您的代码是错误的

if ((pc = (malloc(size * sizeof(pa)) == NULL)))
/* ^^     ^---------------------------------^^^ 
 * ||________________________________________|| 
 * |__________________________________________|
 */
正如您看到的,您正在将
malloc(size*sizeof(pa))==NULL的结果分配给
pc
,这是一个指针,当然是错误的

应该是

if ((pc = malloc(size)) == NULL)
此外,您分配的内存超过了需要的内存,试图使代码紧凑并不能使其更好,您可以通过这样做来避免所有这一切

pc = malloc(size);
if (pc == NULL)
它更清晰,不会导致错误

如果您的代码要保持原样,还需要
释放(pc)
,因为从另一方面讲,每次调用
SwapObjects()
时都会出现内存泄漏

因为它们都只是指针,所以您只需要重新分配指针,而不是不必要地复制数据

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

    pc  = *pa;
    *pa = *pb;
    *pb = pc;
}
然后

SwapObjects(&pa, &pb);
在代码中没有内存泄漏的情况下也会产生同样的效果


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

您可以避免使用
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;
        }
    }

我不能完全肯定我理解你的意图

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

  • 是否要将每个指针引用的内存复制到另一个指针的缓冲区

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

    因此,这意味着您需要要求调用方提供您必须盲目信任的函数缓冲区大小(=不安全!)。您可能正在截断数据,或者更糟糕的是,读取超过缓冲区中有效数据的结尾,读取超过缓冲区的结尾,或者写入超过缓冲区的结尾。除非这个函数可以保证这些缓冲区大小(即函数本身分配缓冲区,或者与调用方有某种形式的强合同),否则你应该认为这个代码是不安全的。 假定参数sizeA和sizeB以字节为单位,而不是以元素为单位

    最后一点,别忘了释放()你的malloc()

  • 建议:坚持解决方案#1,或者如果不可行,请让我们知道用例,以便解决方案可以成为最佳实践示例


    祝你好运

    您可能应该使用“size”参数,而不是“size*sizeof(pa)”。您会遇到什么错误,因为
    sizeof(void)
    没有任何意义,但
    sizeof(pa)==sizeof(void*)
    确实有意义。您现有的代码分配的内存比需要的多,但除此之外,它应该可以工作。如果我有50个指针指向第一个内存块,60个指针指向第二个内存块,该怎么办?并且没有任何机制来枚举这些指针。你认为我应该如何着手“重新分配指针”?我认为如果OP说他们需要物理交换内存内容,那么他们有很好的理由物理交换内存内容,而不是指针。@AnT你能解释为什么有人会这样做吗?是因为他们不喜欢数据存储的位置吗?重要的是,它可以,但在非常特殊的情况下。如果你给出一个原因,请澄清。@AnT我想你的意思是他们通过另一个指针访问它,我没有想到,从上下文来看,似乎有理由假设他们没有,除非在问题中指定。对我来说,似乎有理由假设他们有其他指针,除非问题中另有规定。通常习惯于假设更一般(即更坏)的情况。我想如果OP可以交换指针,他们一开始就不会问这个问题。@AnT你可能是对的,但我的回答解决了这个问题,并建议交换指针,OP可能会接受,也可能不会。你为什么不使用
    memcpy
    ?@iharob:在这种情况下你会如何使用
    memcpy
    ?OP的问题只有我的答案中提到的问题,正如你所看到的,但是OP正确地使用了
    memcpy()
    ,尽管不是
    malloc()
    @iharob:是的,但是这个答案的全部要点是如何在没有运行时大小的缓冲区的情况下做同样的事情。即,如何在没有
    malloc
    的情况下解决问题。如果
    s没有
    malloc`(这就是关键所在),我认为
    memcpy在这里没有任何用处。
    
    void SwapObjects( void *pa, void *pb )
    {
      void *pTemp = pa;
      pa = pb;
      pb = pTemp;
    }
    
    /* 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 );
    }